ORKG Templates

Warning

This is an experimental feature. Bugs can happen and API may change in future releases.

Templates are schema like objects that the ORKG introduced. The template is a logical representation of an object. It can specify how an instance of a specific type can be created in the KG.

Due to the dynamic nature of the templates, the python package needs to create the templates as functions on the fly.

At the moment the python package implements some features of the templates, but not all of them (we are working on that). Here is a list of the features:

  • [x] Materializing a template on the fly

  • [x] Optional parameters

  • [x] Cardinality checks

  • [ ] Strict template (closed) checks

  • [ ] Input validation

  • [x] DF as input

  • [ ] Adding templated instances to a paper construct

  • [ ] Duplicate param handling, and reserved names

  • [ ] Loading instance templates via package

We start by defining our entry point for the templates. (Credentials need to be provided if you want to save new template instance into the graph).

from orkg import ORKG # import base class from package

orkg = ORKG(host="<host-address-is-here>", creds=('email-address', 'password')) # create the connector to the ORKG

We can access the template manager directly to do the following:

Materializing templates

First you need to materialize the template. This is done by one of two methods:

# 1. Materialize all the templates in the system.
orkg.templates.materialize_templates()
>>> 100%|██████████| 108/108 [02:11<00:00,  1.22s/it]

orkg.templates.materialize_templates(['R1', 'R2'])
>>> 100%|██████████| 2/2 [01:08<00:00,  3.12s/it]

## if you want your loading to be silent, you can suppress the loading bar entirely
orkg.templates.materialize_templates(['R1', 'R2'], verbose=False)
>>>

# 2. Materialize a specific template.
orkg.templates.materialize_template('R111')
>>> True

Note: These functions materialize any nested templates that are related to the template being materialized. For instance, if template R1 has two nested templates R2 & R3, then the materialization of R1 will result in the materialization of all three templates R1, R2, and R3.

Documentation

Every template has a documentation string. This is the documentation that is shown when you call the template, or hover over the template function in the IDE.

you can also get it via __doc__:

print(orkg.templates.estimated_value.__doc__)
>>> Creates a template of type R49156 (Estimated value)
>>> :param confidence_interval_95: a nested template, use orkg.templates.confidence_interval_95
>>> :param has_value: a parameter of type Number
>>> :return: a string representing the resource ID of the newly created resource

Using Templates

Once you have materialized the templates, you can use them as any normal python function.

For the sake of simplicity we will shorten the call with the following:

tp = orkg.templates

We now can call any template with a more readable syntax:

For the case of a simple template: (a template with no nested templates as parameters)

tp.confidence_interval_95(has_unit='C', upper_confidence_limit=0.5, lower_confidence_limit=0.01)
>>> <orkg.client.templates.TemplateInstance at 0x7fabeead3890>

This TemplateInstance is a holder class that wraps all the information about the template instance you just created. You can access these methods for this instance:

instance = tp.confidence_interval_95(has_unit='C', upper_confidence_limit=0.5, lower_confidence_limit=0.01)
# you can print the internal representation of the template instance
instance.pretty_print()
>>> {
     "resource": {
         "name": "",
         "classes": [
             "C2003"
         ],
         "values": {
             "P7004": [
                 {
                     "label": "C",
                     "classes": [
                         "C7001"
                     ]
                 }
             ],
             "P19001": [
                 {
                     "text": "0.5"
                 }
             ],
             "P19000": [
                 {
                     "text": "0.01"
                 }
             ]
         }
     }
 }

# you can save it to a file
instance.serialize_to_file('test.json')
>>> None

# you can save it to the graph at any time.
instance.save()
>>> (Success)
 {
     "id": "R247002",
     "label": "Template Instance",
     "created_at": "2022-02-05T12:17:17.847889+01:00",
     "classes": [
         "C2022"
     ],
     "shared": 0,
     "created_by": "00000000-0000-0000-0000-000000000000",
     "_class": "resource",
     "observatory_id": "00000000-0000-0000-0000-000000000000",
     "extraction_method": "UNKNOWN",
     "organization_id": "00000000-0000-0000-0000-000000000000"
 }

You can also create a much more complicated template instance by nesting other templates:

complex_instance = tp.basic_reproduction_number_estimate(
 label = "hello again",
 time_period = tp.time_interval(
     has_end=datetime.date.today(),
     has_beginning=datetime.date.min,
 ),
 location = tp.location(label="Some location", same_as="other location"),
 basic_reproduction_number = tp.basic_reproduction_number_estimate_value_specification(
     tp.confidence_interval_95(
         has_unit="kg",
         upper_confidence_limit=2.3,
         lower_confidence_limit=0.4
     ),
     has_value=1.21
   )
 )

JSON-LD Support

The templates output can be easily serialized into JSON-LD for interoperability.

You can print the templated instance to the console as JSON-LD and serialize to the disc similarly.

instance = some_template_function()
# Print to console
instance.pretty_print(format="json-ld")
>>> {
    "@id": "_:n1",
    "@type": "https://orkg.org/class/C1007",
    "label": "Statistically significant hypothesis"
}

# serialize to file
instance.serialize_to_file(file_path="./disk/location", format="json-ld")

ID support

The templates support the use of IDs for the parameters. This is useful when you want to use a template instance as a parameter for another template instance that is already in the graph.

from orkg import ORKG, OID

# the OID class represents the ORKG ID objects

instance = tp.problem(
    label="Problem 1",
    sub_problem=self.orkg.templates.problem(
        label="Problem 2",
        sub_problem=OID("R70197"), # here we are using an existing ID
        same_as="https://dumpy.url.again",
        description="This is a nested test"
    ),
    same_as="https://dumpy.url",
    description="This is a test"
)

Note: that this recursive template, where it uses itself for one of it’s parameters. This is a valid use case and is supported by the templates.

Optional parameter support

The templates support optional parameters. That means that you can call a template function without passing all the parameters if the schema describes them as optional.

tp.optional_param(label="what!", uses="pyORKG") # here the result parameter is optional and we are not passing it.

tp.optional_param(label="wow!", uses="pyORKG", result="https://google.com") # here we are passing the result parameter.

Multi-value parameter support

The templates support multi-value parameters. So you are able to pass a list of values rather than a single value. This goes for a variety of possible values like nested templates, ground values, or even IDs.

tp.multi_param(label="single!", uses=["pyORKG", "rORKG"]) # here the uses parameter is a list of values.

tp.multi_param(label="single!", uses="pyORKG") # you can pass also uses as a single value if the templates specifies a min cardinality of 1 or less.

Dataframe support

Templates also support ingesting dataframes as parameters. This is particularly useful when you want to add tables of numbers that you created during your analysis to the knowledge graph.

The ingestion relies on the CSVW standard. You can read more about it here: https://www.w3.org/TR/tabular-metadata/