{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial: CUDS API\n", "\n", "
\n", "\n", "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/simphony/docs/v3.9.0?filepath=docs%2Fsource%2Fjupyter%2Fcuds_api.ipynb \"Click to run the tutorial yourself!\")\n", " \n", "
\n", "\n", "This tutorial introduces the CUDS API. The code given here is based on [this](https://github.com/simphony/osp-core/blob/master/examples/api_example.py) example.\n", "\n", "Note that that this tutorial, as all others in this documentation, are Jupyter notebooks that can be downloaded by clicking on the \"Edit on Github\" button on the top right of the page." ] }, { "attachments": { "1de166aa-9888-4fe1-9794-406012a2ebe4.png": { "image/png": "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" } }, "cell_type": "markdown", "metadata": {}, "source": [ "## Background\n", "\n", "CUDS stands for Common Universal Data Structure, and it is used to uniformly represent ontology individuals. In the python implementation of OSP-core, it means that every ontology individual is an instance of the `Cuds` class.\n", "\n", "As every CUDS object is an ontology individual, each CUDS is related to an ontology class via the ontological `is a` relation, and can be connected to other CUDS objects through ontology relationships. In the python implementation of OSP-core, all such ontological classes are instances of the `OntologyClass` class, which is itself a subclass of `OntologyEntity`. The ontology entitites are organized in namespaces.\n", "\n", "In OSP-core, the ontology relationships can be tagged as active or passive relationships. This is done in the ontology installation file. Such feature lets CUDS objects act as containers, so that content of a CUDS object consists of other CUDS objects. This means that a CUDS is a [recursive data structure](https://en.wikipedia.org/wiki/Recursive_data_type). Such active and passive relationships are directed, meaning that they have a source and a target. If a CUDS is the source of a connection via an active relationship to another CUDS, then the former contains the latter. Conversely, if a passive relationship is used, then the latter is contained in the former. Untagged ontology relationships do not define any containment.\n", "\n", "**Note:** currently, each time a source CUDS object is connected to another target CUDS object through an active relationship, an inverse passive relationship is also created, connecting the target CUDS (acting as source) and the source CUDS (acting as target).\n", "\n", "
\n", " \n", "
Containment in CUDS objects. On the graph view of the left hand side, the arrows depict active relationships, while the segment depicts any other untagged ontology relationship. On the right hand side, a containment view is provided.
\n", "
\n", "\n", "The most important functionalities that the CUDS data structure exposes as python methods are the following:\n", "\n", "- `add`: Connects the current CUDS object to one or more CUDS objects through a specific ontology relationship. If the chosen relationship is not an active relationship, one CUDS will not contain the other nor viceversa.\n", "\n", "- `remove`: Despite its name, it does NOT delete the CUDS object itself. Instead, it just disconnects the current CUDS object from one or more CUDS objects.\n", "\n", "- `get`: Returns the CUDS objects connected to the current CUDS object through a specific ontology relationship. \n", "\n", "- `iter`: Similar to the `get` method, it just returns one CUDS objects at a time instead of all at once (python [iterator](https://python.land/deep-dives/python-iterator)), so that memory can be saved.\n", "\n", "- `is_a`: Checks if the CUDS object is an instance of the given ontology class.\n", "\n", "In addition, other important functionalities are exposed as python properties:\n", "\n", "- `oclass`: The ontology class of the ontology individual represented by the CUDS object. If the individual belongs to multiple classes, only one of them is referenced by the property.\n", "\n", "- `uid`: A unique ID identifying an ontology individual.\n", "\n", "- `iri`: The [Internationalized Resource Identifier](https://fusion.cs.uni-jena.de/fusion/blog/2016/11/18/iri-uri-url-urn-and-their-differences/) of the CUDS object. It consists of a CUDS namespace prefix and the unique ID of the CUDS object. This will be further clarified in the tutorial.\n", "\n", "- `attributes`: The values of the ontology attributes of an individual (also known as [data properties](https://www.w3.org/TR/owl2-syntax/#Data_Properties) in [OWL](https://en.wikipedia.org/wiki/Web_Ontology_Language)) may also be accessed and modified as python properties of the CUDS objects. For example: `cuds_object.name = \"Bob\"`.\n", "\n", "There are some advanced functionalities NOT covered in this tutorial. Among them, we highlight the `update` method, which is covered in the [wrapper tutorial](multiple_wrappers.ipynb), where it can be seen in action. For a complete list of available methods and properties, check the API reference. That whole set of methods and attributes constitutes the CUDS [API](https://en.wikipedia.org/wiki/API).\n", "\n", "[//]: # (TODO: Link to API reference.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Let's get hands on\n", "In this tutorial, we will work with the `city` namespace, the example namespace from OSP-core. It consists of concepts from the example [city ontology](https://github.com/simphony/osp-core/blob/master/osp/core/ontology/docs/city.ontology.yml).\n", "\n", "[//]: # (TODO: simple graphical representation of the city ontology.)" ] }, { "cell_type": "markdown", "metadata": { "nteract": { "transient": { "deleting": false } } }, "source": [ "The first step is to install the city ontology. Use the tool pico for this. If you want to know more about ontology installation, check the documentation on the [pico ontology installation tool](https://simphony.readthedocs.io/en/v3.9.0/utils.html#pico-installs-cuds-ontologies), [YAML ontology installation files](https://simphony.readthedocs.io/en/v3.9.0/working_with_ontologies.html#osp-core-yaml-ontology-format), and [installing OWL ontologies](https://simphony.readthedocs.io/en/latest/working_with_ontologies.html#owl-ontologies-and-rdfs-vocabularies)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "INFO 2021-04-01 13:40:41,433 [osp.core.ontology.installation]: Will install the following namespaces: ['city']\n", "INFO 2021-04-01 13:40:41,448 [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-04-01 13:40:41,476 [osp.core.ontology.yml.yml_parser]: You can now use `from osp.core.namespaces import city`.\n", "INFO 2021-04-01 13:40:41,476 [osp.core.ontology.parser]: Loaded 202 ontology triples in total\n", "INFO 2021-04-01 13:40:41,491 [osp.core.ontology.installation]: Installation successful\n" ] } ], "source": [ "!pico install city" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then you can import the `city` namespace." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [] }, "outputs": [], "source": [ "# If you just installed the ontology from within this notebook and this line doesn't work, please restart the kernel and run this cell again.\n", "from osp.core.namespaces import city" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You are now creating some CUDS objects that you are going to use to try out the functionalities of the CUDS data structure." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "c = city.City(name=\"Freiburg\", coordinates=[47, 7]) # Ontology individual representing the city of Freiburg.\n", "p1 = city.Citizen(name=\"Peter\") # Ontology indidual representing a specific person, \"Peter\".\n", "p2 = city.Citizen(name=\"Anne\") # Ontology individual representing another specific person, \"Anne\"." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The names `c, p1, p2` are assigned to the newly created CUDS objects. The keyword arguments `name` and `coordinates` let you directly assign values for such ontology attributes (also known as [data properties](https://www.w3.org/TR/owl2-syntax/#Data_Properties) in [OWL](https://en.wikipedia.org/wiki/Web_Ontology_Language)) to the new CUDS objects. The available ontology attributes for each ontology class depend on the specific class being instantiated. For example, the ontology attribute `name` is available for both the _City_ and the _Citizen_ ontology classes in the sample _City_ ontology. The attribute `coordinates` is available for the _City_ ontology class, but not for the _Citizen_ class." ] }, { "cell_type": "markdown", "metadata": { "nteract": { "transient": { "deleting": false } } }, "source": [ "### Functionalities exposed as python properties" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Each CUDS object has a unique identifier (UID), which can be accessed using the `uid` property:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "uid of c: e0b721ae-6004-4834-80f1-e6e979952d1f\n", "uid of p1: 63874785-0de6-43ad-8669-999482501ad1\n", "uid of p2: 39c7334f-ef62-4dbc-ae2e-390d7f3ca641\n" ] } ], "source": [ "print(\"uid of c: \" + str(c.uid))\n", "print(\"uid of p1: \" + str(p1.uid))\n", "print(\"uid of p2: \" + str(p2.uid))" ] }, { "cell_type": "markdown", "metadata": { "nteract": { "transient": { "deleting": false } } }, "source": [ "Similarly, each CUDS object has an [IRI](https://fusion.cs.uni-jena.de/fusion/blog/2016/11/18/iri-uri-url-urn-and-their-differences/), which serves to reference it in the [Semantic Web](https://en.wikipedia.org/wiki/Semantic_Web) and improves the compatibility of the CUDS format with the [Resource Description Framework](https://en.wikipedia.org/wiki/Resource_Description_Framework) data model. Note that the IRI of each CUDS object contains its unique identifier." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "nteract": { "transient": { "deleting": false } }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "IRI of c: http://www.osp-core.com/cuds#e0b721ae-6004-4834-80f1-e6e979952d1f\n", "IRI of p1: http://www.osp-core.com/cuds#63874785-0de6-43ad-8669-999482501ad1\n", "IRI of p2: http://www.osp-core.com/cuds#39c7334f-ef62-4dbc-ae2e-390d7f3ca641\n" ] } ], "source": [ "print(\"IRI of c: \" + str(c.iri))\n", "print(\"IRI of p1: \" + str(p1.iri))\n", "print(\"IRI of p2: \" + str(p2.iri))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The class of the ontology individual represented by the CUDS object can be queried as well:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "oclass of c: city.City\n", "oclass of p1: city.Citizen\n", "oclass of p2: city.Citizen\n" ] } ], "source": [ "print(\"oclass of c: \" + str(c.oclass))\n", "print(\"oclass of p1: \" + str(p1.oclass))\n", "print(\"oclass of p2: \" + str(p2.oclass))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `uid`, `iri` and `oclass` properties **cannot be modified**." ] }, { "cell_type": "markdown", "metadata": { "nteract": { "transient": { "deleting": false } } }, "source": [ "Finally, the values of the ontology attributes of an individual can be easily **accessed and modified** using the dot notation." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "nteract": { "transient": { "deleting": false } }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Name of c: Freiburg. Coordinates of c: [47 7].\n", "Name of p1: Peter\n", "Name of p2: Anne\n", "\n", "Change the name of Peter.\n", "Name of p1: Bob.\n" ] } ], "source": [ "print(f\"Name of c: {c.name}. Coordinates of c: {c.coordinates}.\" )\n", "print(\"Name of p1: \" + str(p1.name))\n", "print(\"Name of p2: \" + str(p2.name))\n", "\n", "print(f\"\\nChange the name of {p1.name}.\")\n", "p1.name = \"Bob\"\n", "print(f\"Name of p1: {p1.name}.\")" ] }, { "cell_type": "markdown", "metadata": { "nteract": { "transient": { "deleting": false } } }, "source": [ "### Functionalities exposed as python methods" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we may connect the two citizens to our city object:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "c.add(p1, rel=city.hasInhabitant)\n", "c.add(p2, rel=city.hasInhabitant)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the relationship type between the city and its two citizens in this case is 'hasInhabitant'. In our context, this means that Anne and Peter are Freiburg inhabitants. Moreover, in the [city ontology](https://github.com/simphony/osp-core/blob/master/osp/core/ontology/docs/city.ontology.yml), this relationship is defined as an active relationship. This means that Anne and Peter are not only connected to Freiburg, but are also contained in the Freiburg CUDS object." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we would like to iterate over the objects contained in the city object. We do so by using the `iter` function:\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "uid: 63874785-0de6-43ad-8669-999482501ad1\n", "uid: 39c7334f-ef62-4dbc-ae2e-390d7f3ca641\n" ] } ], "source": [ "for el in c.iter():\n", " print(\"uid: \" + str(el.uid))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can `get` a target object from a CUDS object if we have a UID of one of its immediate contained objects. This will not work if the target object is not contained in the CUDS object, but just connected to it." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "city.Citizen: 63874785-0de6-43ad-8669-999482501ad1\n", "None\n" ] } ], "source": [ "print(c.get(p1.uid)) # `p1`is contained in `c` because they are connected through an active relationship.\n", "print(p1.get(c.uid)) # `c` is connected to `p1`, but it is NOT contained in `p1`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also filter the contained objects by type: " ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[, ]\n" ] } ], "source": [ "print(c.get(oclass=city.Citizen))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We remove objects using the `remove()` function. Despite its name, this just disconnects the target object from the CUDS, but does NOT delete the target object from the memory." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "city.Citizen: 63874785-0de6-43ad-8669-999482501ad1\n", "None\n" ] } ], "source": [ "c.remove(p1)\n", "# c.remove(p1.uid) also works!\n", "print(p1) # `p1` still exists,\n", "print(c.get(p1.uid)) # but is no longer connected neither contained in `c`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's close this tutorial by adding some neighborhoods in a loop," ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "for i in range(6):\n", " c.add(city.Neighborhood(name=\"neighborhood %s\" % i))" ] }, { "cell_type": "markdown", "metadata": { "nteract": { "transient": { "deleting": false } } }, "source": [ "and then verifying that they are indeed neighborhoods, just to also try the `is_a` method.\n", "\n" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "nteract": { "transient": { "deleting": false } } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all(n.is_a(city.Neighborhood) for n in c.get(oclass=city.Neighborhood))" ] }, { "cell_type": "markdown", "metadata": { "nteract": { "transient": { "deleting": false } } }, "source": [ "The existing ontology individuals and the relationships among them have been depicted below, using the utility `pretty_print` (see the [Utilities section](https://simphony.readthedocs.io/en/v3.9.0/utils.html?highlight=pretty_print)). Note that some attributes that were not specified were set automatically to the default values specified in the ontology." ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "nteract": { "transient": { "deleting": false } }, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "- Cuds object named :\n", " uuid: e0b721ae-6004-4834-80f1-e6e979952d1f\n", " type: city.City\n", " superclasses: city.City, city.GeographicalPlace, city.PopulatedPlace, cuba.Entity\n", " values: coordinates: [47 7]\n", " description: \n", " To Be Determined\n", "\n", " |_Relationship city.hasInhabitant:\n", " | - city.Citizen cuds object named :\n", " | uuid: 39c7334f-ef62-4dbc-ae2e-390d7f3ca641\n", " | age: 25\n", " |_Relationship city.hasPart:\n", " - city.Neighborhood cuds object named :\n", " . uuid: 79eec4f9-55c5-464d-b6c3-dc4382e55476\n", " . coordinates: [0 0]\n", " - city.Neighborhood cuds object named :\n", " . uuid: 50fa8dac-2f5f-4b2c-ab8a-24f7f1b41f2c\n", " . coordinates: [0 0]\n", " - city.Neighborhood cuds object named :\n", " . uuid: f6c20bfa-c29b-46bb-a5f5-8bc88b3e3621\n", " . coordinates: [0 0]\n", " - city.Neighborhood cuds object named :\n", " . uuid: e161ea1c-40d8-4556-93ad-dfd4d178d669\n", " . coordinates: [0 0]\n", " - city.Neighborhood cuds object named :\n", " . uuid: a3af8db2-28cd-457b-84ed-b420be5212c2\n", " . coordinates: [0 0]\n", " - city.Neighborhood cuds object named :\n", " uuid: 8de47383-4416-44be-99dc-e5903b1d14dd\n", " coordinates: [0 0]\n" ] } ], "source": [ "from osp.core.utils import pretty_print\n", "pretty_print(c)" ] } ], "metadata": {}, "nbformat": 4, "nbformat_minor": 4 }