{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Tutorial: Ontology interface\n",
"\n",
"\n",
"\n",
"[](https://mybinder.org/v2/gh/simphony/docs/v3.9.0?filepath=docs%2Fsource%2Fjupyter%2Fontology_interface.ipynb \"Click to run the tutorial yourself!\")\n",
" \n",
"\n",
"\n",
"\n",
"This tutorial introduces the interface to the installed ontologies. The code presented is based on [this example](https://github.com/simphony/osp-core/blob/master/examples/ontology_example.py)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Background"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In an ontological framework, ontology entities are used as a knowledge representation form. Those can be further categorized in two groups: ontology individuals ([assertional knowledge](https://en.wikipedia.org/wiki/Abox)), and ontology classes, relationships and attributes ([terminological knowledge](https://en.wikipedia.org/wiki/Tbox)).\n",
"\n",
"In a [previous tutorial](./cuds_api.ipynb), we have discussed how to work with CUDS objects, which represent ontology individuals. In this tutorial, we present the API of all the other entities instead: ontology classes, relationships and attributes. These are defined in an ontology installation file in [YAML](../working_with_ontologies.md#osp-core-yaml-ontology-format) or [OWL](../working_with_ontologies.md#owl-ontologies-and-rdfs-vocabularies) format. The presented API enables you to access the entities and navigate within an ontology."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this tutorial, we will work both with the `city` namespace, the example namespace from OSP-core, and the `math` namespace from the [Elementary Multiperspective Material Ontology (EMMO)](https://github.com/emmo-repo/EMMO), for which an installation file is also provided with OSP-core.\n",
"\n",
"Please install the ontologies running the commands below if you have not installed them yet."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"INFO 2021-03-31 16:16:53,174 [osp.core.ontology.installation]: Will install the following namespaces: ['city']\n",
"INFO 2021-03-31 16:16:53,187 [osp.core.ontology.yml.yml_parser]: Parsing YAML ontology file /home/jose/.local/lib/python3.9/site-packages/osp/core/ontology/docs/city.ontology.yml\n",
"INFO 2021-03-31 16:16:53,209 [osp.core.ontology.yml.yml_parser]: You can now use `from osp.core.namespaces import city`.\n",
"INFO 2021-03-31 16:16:53,209 [osp.core.ontology.parser]: Loaded 202 ontology triples in total\n",
"INFO 2021-03-31 16:16:53,223 [osp.core.ontology.installation]: Installation successful\n",
"INFO 2021-03-31 16:16:53,753 [osp.core.ontology.installation]: Will install the following namespaces: ['emmo']\n",
"INFO 2021-03-31 16:16:53,756 [osp.core.ontology.parser]: Parsing /home/jose/.local/lib/python3.9/site-packages/osp/core/ontology/docs/emmo.yml\n",
"INFO 2021-03-31 16:16:53,756 [osp.core.ontology.parser]: Downloading https://raw.githubusercontent.com/emmo-repo/emmo-repo.github.io/master/versions/1.0.0-alpha2/emmo-inferred.owl\n",
"INFO 2021-03-31 16:16:54,299 [osp.core.ontology.parser]: Parsing /tmp/tmpvqey417g-emmo\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import mereotopology`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import physical`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import top`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import semiotics`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import perceptual`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import reductionistic`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import holistic`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import physicalistic`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import math`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import properties`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import materials`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import metrology`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import models`.\n",
"INFO 2021-03-31 16:16:54,897 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import manufacturing`.\n",
"INFO 2021-03-31 16:16:54,898 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import isq`.\n",
"INFO 2021-03-31 16:16:54,898 [osp.core.ontology.parser]: You can now use `from osp.core.namespaces import siunits`.\n",
"INFO 2021-03-31 16:16:54,901 [osp.core.ontology.parser]: Loaded 4664 ontology triples in total\n",
"INFO 2021-03-31 16:16:55,083 [osp.core.ontology.installation]: Installation successful\n"
]
}
],
"source": [
"# Install the ontologies\n",
"!pico install city\n",
"!pico install emmo"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Accessing entities: the namespace object\n",
"\n",
"To access ontology entities, we first need to know the aliases of the installed ontology namespaces. In each ontology [YAML installation file](../working_with_ontologies.md#owl-ontologies-and-rdfs-vocabularies), the namespace(s) that it contains is(are) stated at the top of the file. For example, at the top of the [city ontology installation file](https://github.com/simphony/osp-core/blob/master/osp/core/ontology/docs/city.ontology.yml) you may find:\n",
"\n",
"```yaml\n",
"---\n",
"version: \"0.0.3\"\n",
"\n",
"namespace: \"city\"\n",
"\n",
"ontology:\n",
" ...\n",
"```\n",
"\n",
"Alternatively, you can use [pico ontology installation tool](../utils.md#pico) to see the installed namespaces:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Packages:\n",
"\t- city\n",
"\t- emmo\n",
"Namespaces:\n",
"\t- xml\n",
"\t- rdf\n",
"\t- rdfs\n",
"\t- xsd\n",
"\t- cuba\n",
"\t- isq\n",
"\t- ns1\n",
"\t- ns2\n",
"\t- owl\n",
"\t- city\n",
"\t- mereotopology\n",
"\t- physical\n",
"\t- top\n",
"\t- semiotics\n",
"\t- perceptual\n",
"\t- reductionistic\n",
"\t- holistic\n",
"\t- physicalistic\n",
"\t- math\n",
"\t- properties\n",
"\t- materials\n",
"\t- metrology\n",
"\t- models\n",
"\t- manufacturing\n",
"\t- siunits\n"
]
}
],
"source": [
"!pico list"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Once we know the name of the namespace that we want to use, we import it in python. For this tutorial, we are importing the namespaces `city` and `math`. Through those imported namespace python objects, the entities within the namespaces can be accessed:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from osp.core.namespaces import city\n",
"from osp.core.namespaces import math"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There are several ways to access an ontology entity in OSP-core, which are summarized by the following list and will be demonstrated shortly after.\n",
"\n",
"- By **suffix**. For example, for the namespace `city`, whose [IRI](https://fusion.cs.uni-jena.de/fusion/blog/2016/11/18/iri-uri-url-urn-and-their-differences/) is `http://www.osp-core.com/city#`, fetching by the suffix `Citizen` would return the ontology entity with IRI `http://www.osp-core.com/city#Citizen`.\n",
"\n",
"- By **label**. Fetchs the entity by the label that has been assigned to it using either the `rdfs:label` or `skos:prefLabel` predicates.\n",
"\n",
"- By **IRI**. The full [IRI](https://fusion.cs.uni-jena.de/fusion/blog/2016/11/18/iri-uri-url-urn-and-their-differences/) of an ontology entity is provided in order to fetch it.\n",
"\n",
"- By **string**. Using a string, for example `\"city.LivingBeing\"`. This is only useful in some special cases."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The **most convenient way** to access an ontology entity is using the **dot notation** in python. For example, `city.Citizen`. This method is a shorthand for fetching by suffix or label: \n",
"\n",
"- When the keyword `reference_by_label` is set to `True` (enabled) in the [ontology YAML installation file](../working_with_ontologies.md), the dot notation is a shorthand for fetching by label. This keyword is **enabled** in the `math` namespace.\n",
"\n",
"- When the keyword `reference_by_label` is set to `False` (disabled) or not set, the dot notation is a shorthand for fetching by suffix instead. This keyword is **disabled** in the `city` namespace."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"To get a list of all the entities available within a namespace, run `list(namespace)`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"
Tip
\n",
" \n",
"The dot notation supports IPython autocompletion. For example, when working on a Jupyter notebook, once the namespace has been imported, it is possible to get suggestions for the entity names by writing `namespace.` and pressing TAB.\n",
" \n",
"
"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Accessing an ontology entity by suffix**\n",
"\n",
"Let's fetch the Citizen class, whose IRI is `http://www.osp-core.com/city#Citizen`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The keyword, `reference_by_label` is set to `False`, so one can just use the dot notation. "
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"city.Citizen"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another alternative is using the `get_from_suffix` method from the namespace object. This is useful when the suffix contains characters that Python does not accept as property names, such as spaces or dashes."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"city.get_from_suffix('Citizen')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Note that the suffix is case sensitive, and therefore the following would produce an error."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# city.citizen # -> Fails."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Accessing an ontology entity by label**\n",
"\n",
"Let's fetch the Integer class, whose IRI is `http://emmo.info/emmo/middle/math#EMMO_f8bd64d5_5d3e_4ad4_a46e_c30714fecb7f`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The keyword `reference_by_label` is set to `True`, so we just use the dot notation."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"math.Integer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Another alternative is using the square bracket notation on the namespace object. This is useful when the suffix contains characters that Python does not accept as property names, such as spaces or dashes."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"math['Integer']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Fetching by label is NOT case sensitive when using the dot notation, but it is when using square brackets, so the following behavior is expected."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# math['integer'] # -> Fails.\n",
"math.integer # -> Works."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Accessing an ontology entity by IRI**\n",
"\n",
"This is only possible using the `get_from_iri` method from the namespace object. For example, let's fetch the Integer entity again."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"math.get_from_iri('http://emmo.info/emmo/middle/math#EMMO_f8bd64d5_5d3e_4ad4_a46e_c30714fecb7f')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Access entities using a string**\n",
"\n",
"Sometimes you only have a string refering to an entity. Using the `get_entity` function you can get the corresponding python object easily:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"You can get an entity with a string\n",
"city.LivingBeing\n",
"True\n"
]
}
],
"source": [
"from osp.core.namespaces import get_entity # noqa: E402\n",
"\n",
"print(\"\\nYou can get an entity with a string\")\n",
"print(get_entity(\"city.LivingBeing\"))\n",
"print(get_entity(\"city.LivingBeing\") == city.LivingBeing)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Accessing an entity's name, IRI and namespace"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Each ontology entity has an associated name which can be accessed using the `name` property. "
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"tags": []
},
"outputs": [
{
"data": {
"text/plain": [
"'LivingBeing'"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"city.LivingBeing.name"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The IRI of an entity might be accessed using the `iri` property."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"rdflib.term.URIRef('http://emmo.info/emmo/middle/math#EMMO_18d180e4_5e3e_42f7_820c_e08951223486')"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"math.Real.iri"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In addition, it is possible to get the namespace object to which the entity belongs using the `namespace` property."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"math.Equation.namespace"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Accessing super- and subclasses\n",
"\n",
"Using the properties `superclasses` and `subclasses` it is easy to navigate the ontology. Direct superclasses and subclasses can also be accessed:"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"You can access the superclasses and the subclasses\n",
"{, }\n",
"{, , }\n",
"\n",
"You can access the direct superclasses and subclasses\n",
"{}\n",
"{}\n",
"\n",
"You can access a description of the entities\n",
"A being that lives\n",
"\n",
"You can test if one entity is a subclass / superclass of another\n",
"True\n",
"True\n"
]
}
],
"source": [
"print(\"\\nYou can access the superclasses and the subclasses\")\n",
"print(city.LivingBeing.superclasses)\n",
"print(city.LivingBeing.subclasses)\n",
"\n",
"print(\"\\nYou can access the direct superclasses and subclasses\")\n",
"print(city.LivingBeing.direct_superclasses)\n",
"print(city.LivingBeing.direct_subclasses)\n",
"\n",
"print(\"\\nYou can access a description of the entities\")\n",
"print(city.LivingBeing.description)\n",
"\n",
"print(\"\\nYou can test if one entity is a subclass / superclass of another\")\n",
"print(city.Person.is_subclass_of(city.LivingBeing))\n",
"print(city.LivingBeing.is_superclass_of(city.Person))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Testing the type of the entities\n",
"\n",
"In the ontology, three types of entities can be defined: classes, relationships and attributes. OSP-core has its own vocabulary, the [CUBA namespace](../working_with_ontologies.md#the-cuba-namespace), which describes, among other things, such entity types. Relationships are subclasses of `CUBA.RELATIONSHIP` and attributes are subclasses of `CUBA.ATTRIBUTE`. There are different Python objects for the different entity types. You can use both to check which type of entity you are dealing with:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"You can test if an entity is a class\n",
"True\n",
"True\n",
"\n",
"You can test if an entity is a relationship\n",
"True\n",
"True\n",
"\n",
"You can test if an entity is a attribute\n",
"True\n",
"True\n"
]
}
],
"source": [
"from osp.core.namespaces import cuba # noqa: E402\n",
"\n",
"# These are the classes for the ontology entities\n",
"from osp.core.ontology import ( # noqa: F401, E402\n",
" OntologyEntity,\n",
" OntologyClass,\n",
" OntologyRelationship,\n",
" OntologyAttribute\n",
")\n",
"\n",
"print(\"\\nYou can test if an entity is a class\")\n",
"print(isinstance(city.LivingBeing, OntologyClass))\n",
"print(not city.LivingBeing.is_subclass_of(cuba.relationship)\n",
" and not city.LivingBeing.is_subclass_of(cuba.attribute))\n",
"\n",
"print(\"\\nYou can test if an entity is a relationship\")\n",
"print(isinstance(city.hasInhabitant, OntologyRelationship))\n",
"print(city.hasInhabitant.is_subclass_of(cuba.relationship))\n",
"\n",
"print(\"\\nYou can test if an entity is a attribute\")\n",
"print(isinstance(city.name, OntologyAttribute))\n",
"print(city.name.is_subclass_of(cuba.attribute))\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Operations specific to ontology classes\n",
"\n",
"The different types of entities differ in the operations they offer. For classes, you can access the attributes:"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"You can get the attributes of an ontology class and their defaults\n",
"{: (rdflib.term.Literal('John Smith'), False, None), : (rdflib.term.Literal('25', datatype=rdflib.term.URIRef('http://www.w3.org/2001/XMLSchema#integer')), False, None)}\n",
"\n",
"You can get the non-inherited attributes and their defaults\n",
"{}\n",
"{: (rdflib.term.Literal('John Smith'), False, None), : (rdflib.term.Literal('25', datatype=rdflib.term.URIRef('http://www.w3.org/2001/XMLSchema#integer')), False, None)}\n"
]
}
],
"source": [
"print(\"\\nYou can get the attributes of an ontology class and their defaults\")\n",
"print(city.Citizen.attributes)\n",
"\n",
"print(\"\\nYou can get the non-inherited attributes and their defaults\")\n",
"print(city.Citizen.own_attributes)\n",
"print(city.LivingBeing.own_attributes)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In addition, OSP-core has special support for the `owl:Restriction` and `owl:Composition` classes of the [Web Ontology Language (OWL)](https://en.wikipedia.org/wiki/Web_Ontology_Language) (check the [OWL ontology specification](https://www.w3.org/TR/owl2-syntax/) for more details). Such OWL classes are represented by the python classes `Restriction` and `Composition`. See [operations specific to ontology axioms](#Operations-specific-to-ontology-axioms) for more information.\n",
"\n",
"For example, in the city ontology, the citizens have a restriction on the name and age attributes: a citizen must have exactly one name and one age. These axioms can be accessed using the `axioms` property, which returns both the restriction and compositions affecting the class."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('city.name QUANTIFIER.EXACTLY 1', 'city.age QUANTIFIER.EXACTLY 1')"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tuple(str(x) for x in city.Citizen.axioms)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Operations specific to ontology axioms"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For restrictions, the quantifier, the target, the restriction type and the relationship/attribute (depending on whether it is a restriction of the relationship type or attribute type) may be accessed."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"city.name QUANTIFIER.EXACTLY 1\n",
"QUANTIFIER.EXACTLY\n",
"1\n",
"RTYPE.ATTRIBUTE_RESTRICTION\n",
"city.name\n"
]
}
],
"source": [
"restriction = city.Citizen.axioms[0]\n",
"print(restriction)\n",
"print(restriction.quantifier)\n",
"print(restriction.target)\n",
"print(restriction.rtype)\n",
"print(restriction.attribute)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For compositions, both the operator and operands can be accesed."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(math.Mathematical OPERATOR.AND perceptual.Symbol)\n",
"OPERATOR.AND\n",
"[, ]\n"
]
}
],
"source": [
"from osp.core.ontology.oclass_composition import Composition\n",
"composition = tuple(x for x in math.Integer.axioms if type(x) is Composition)[0]\n",
"print(composition)\n",
"print(composition.operator)\n",
"print(composition.operands)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Operations specific to ontology relationships\n",
"\n",
"You can access the inverse of relationships."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"You can get the inverse of a relationship\n",
"city.INVERSE_OF_hasInhabitant\n"
]
}
],
"source": [
"print(\"\\nYou can get the inverse of a relationship\")\n",
"print(city.hasInhabitant.inverse)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Operations specific to attributes\n",
"\n",
"You can acces the datatype and the argument name of attributes."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"You can get the argument name of an attribute. The argument name is used as keyword argument when instantiating CUDS objects.\n",
"age\n",
"\n",
"You can get the datatype of attributes\n",
"http://www.w3.org/2001/XMLSchema#integer\n",
"\n",
"You can use the attribute to convert values to the datatype of the attribute\n",
" 10\n",
"\n",
"And likewise to convert values to the python basic type associated with the datatype of the attribute.\n",
" 5\n"
]
}
],
"source": [
"print(\"\\nYou can get the argument name of an attribute. \"\n",
" \"The argument name is used as keyword argument when instantiating CUDS objects.\")\n",
"print(city.age.argname)\n",
"\n",
"print(\"\\nYou can get the datatype of attributes\")\n",
"print(city.age.datatype)\n",
"\n",
"print(\"\\nYou can use the attribute to convert values \"\n",
" \"to the datatype of the attribute\")\n",
"result = city.age.convert_to_datatype(\"10\")\n",
"print(type(result), result)\n",
"\n",
"print(\"\\nAnd likewise to convert values to the python basic type \"\n",
" \"associated with the datatype of the attribute.\")\n",
"result = city.name.convert_to_basic_type(5)\n",
"print(type(result), result)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Check the API Reference for more details on the methods [_convert_to_datatype_](../api_ref.md#osp.core.ontology.attribute.OntologyAttribute.convert_to_datatype) and [_convert_to_basic_type_](../api_ref.md#osp.core.ontology.attribute.OntologyAttribute.convert_to_basic_type)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Creating CUDS using ontology classes\n",
"\n",
"You can call ontology classes to create CUDS objects. To learn more, have a look at the [CUDS API tutorial](./cuds_api.ipynb)."
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"tags": []
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"You can instantiate CUDS objects using ontology classes\n",
"city.Citizen: e0947100-9c40-415f-92c8-a86b796dbb01\n",
"\n",
"You can check if a CUDS object is an instance of a ontology class\n",
"True\n",
"True\n",
"\n",
"You can get the ontology class of a CUDS object.\n",
"city.Citizen\n"
]
}
],
"source": [
"print(\"\\nYou can instantiate CUDS objects using ontology classes\")\n",
"print(city.Citizen(name=\"Test Person\", age=42))\n",
"\n",
"print(\"\\nYou can check if a CUDS object is an instance of a ontology class\")\n",
"print(city.Citizen(name=\"Test Person\", age=42).is_a(city.Citizen))\n",
"print(city.Citizen(name=\"Test Person\", age=42).is_a(city.LivingBeing))\n",
"\n",
"print(\"\\nYou can get the ontology class of a CUDS object.\")\n",
"print(city.Citizen(name=\"Test Person\", age=42).oclass)"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 4
}