{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Managing the session contents\n", "\n", "
\n", "\n", "[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/simphony/docs/v4.0.0?filepath=docs%2Fusage%2Fsessions%2Fmanagement.ipynb \"Click to run this tutorial yourself!\")\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As said, sessions can be though of as a \"box\" that stores ontology individuals. Consequently, adding and removing individuals are among the operations that can be performed on them. \n", "\n", "As described in [one of the previous sections](../assertional_knowledge.ipynb), in SimPhoNy, an ontology individual is characterized by\n", "\n", "- the information about the ontology individual itself such as the classes it belongs to, its label and its attributes;\n", "- the connections to other ontology individuals." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The methods [add](../../api_reference.md#simphony_osp.session.Session.add) and [delete](../../api_reference.md#simphony_osp.session.delete) try to accommodate this definition. To see how they work, consider a city example again." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from simphony_osp.namespaces import city\n", "\n", "freiburg = city.City(name=\"Freiburg\", coordinates=[47.997791, 7.842609])\n", "\n", "neighborhoods = {\n", " city.Neighborhood(name=name, coordinates=coordinates)\n", " for name, coordinates in [\n", " ('Altstadt', [47.99525, 7.84726]),\n", " ('Stühlinger', [47.99888, 7.83774]),\n", " ('Neuburg', [48.00021, 7.86084]),\n", " ('Herdern', [48.00779, 7.86268]),\n", " ('Brühl', [48.01684, 7.843]),\n", " ]\n", "}\n", "\n", "citizen_1 = city.Citizen(name='Nikola', age=35)\n", "citizen_2 = city.Citizen(name='Lena', age=70)\n", "\n", "freiburg[city.hasPart] |= neighborhoods\n", "freiburg[city.hasInhabitant] += citizen_1, citizen_2" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "SimPhoNy semantic2dot\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#21317ff8-e405-4333-9c2c-a10462e03811\n", "\n", "21317ff8...811\n", "classes: Citizen (city)\n", "name: Lena\n", "age: 70\n", "session: 0x5608d3a41780\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#cc02ad20-4c05-4257-8f40-47bb0e243934\n", "\n", "cc02ad20...934\n", "classes: City (city)\n", "coordinates: [47.997791  7.842609]\n", "name: Freiburg\n", "session: 0x5608d3a41780\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#cc02ad20-4c05-4257-8f40-47bb0e243934->https___www.simphony-osp.eu_entity#21317ff8-e405-4333-9c2c-a10462e03811\n", "\n", "\n", "has inhabitant (city)\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#18bb022d-3c87-4d0d-8bde-527ffe5b877c\n", "\n", "18bb022d...77c\n", "classes: Neighborhood (city)\n", "coordinates: [47.99888  7.83774]\n", "name: Stühlinger\n", "session: 0x5608d3a41780\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#cc02ad20-4c05-4257-8f40-47bb0e243934->https___www.simphony-osp.eu_entity#18bb022d-3c87-4d0d-8bde-527ffe5b877c\n", "\n", "\n", "has part (city)\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#596e4a1d-bb20-4d3f-9d03-05f32a699c41\n", "\n", "596e4a1d...c41\n", "classes: Citizen (city)\n", "age: 35\n", "name: Nikola\n", "session: 0x5608d3a41780\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#cc02ad20-4c05-4257-8f40-47bb0e243934->https___www.simphony-osp.eu_entity#596e4a1d-bb20-4d3f-9d03-05f32a699c41\n", "\n", "\n", "has inhabitant (city)\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#7824a475-52e0-48b3-ac15-95cbe1d11298\n", "\n", "7824a475...298\n", "classes: Neighborhood (city)\n", "coordinates: [48.01684  7.843  ]\n", "name: Brühl\n", "session: 0x5608d3a41780\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#cc02ad20-4c05-4257-8f40-47bb0e243934->https___www.simphony-osp.eu_entity#7824a475-52e0-48b3-ac15-95cbe1d11298\n", "\n", "\n", "has part (city)\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#ec1484ec-94df-4bfc-bf37-ece246888089\n", "\n", "ec1484ec...089\n", "classes: Neighborhood (city)\n", "name: Neuburg\n", "coordinates: [48.00021  7.86084]\n", "session: 0x5608d3a41780\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#cc02ad20-4c05-4257-8f40-47bb0e243934->https___www.simphony-osp.eu_entity#ec1484ec-94df-4bfc-bf37-ece246888089\n", "\n", "\n", "has part (city)\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#4070b09c-ab77-439b-8404-5e4fd1e0662e\n", "\n", "4070b09c...62e\n", "classes: Neighborhood (city)\n", "name: Altstadt\n", "coordinates: [47.99525  7.84726]\n", "session: 0x5608d3a41780\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#cc02ad20-4c05-4257-8f40-47bb0e243934->https___www.simphony-osp.eu_entity#4070b09c-ab77-439b-8404-5e4fd1e0662e\n", "\n", "\n", "has part (city)\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#d136fbd0-3eb8-482b-908f-b5755cd94459\n", "\n", "d136fbd0...459\n", "classes: Neighborhood (city)\n", "name: Herdern\n", "coordinates: [48.00779  7.86268]\n", "session: 0x5608d3a41780\n", "\n", "\n", "\n", "https___www.simphony-osp.eu_entity#cc02ad20-4c05-4257-8f40-47bb0e243934->https___www.simphony-osp.eu_entity#d136fbd0-3eb8-482b-908f-b5755cd94459\n", "\n", "\n", "has part (city)\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from simphony_osp.tools import semantic2dot # explained in a later section\n", "\n", "semantic2dot(freiburg, *neighborhoods, citizen_1, citizen_2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "
Tip
\n", " \n", "On most web browsers (including mobile ones), you can right-click the picture above and then click \"open in new tab\" to see the picture in its full size.\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then create a new session to transfer individuals to." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "from simphony_osp.session import Session\n", "\n", "session = Session()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Passing any individual to the method [add](../../api_reference.md#simphony_osp.session.Session.add) of the new session creates a copy of it. The copy contained in the new session is assigned the same identifier as the original." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "([],\n", " 'Freiburg',\n", " ,\n", " set() )" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "freiburg_copy = session.add(freiburg)\n", "list(session), freiburg_copy.name, freiburg_copy.coordinates, freiburg_copy.get()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the example above, the variable `freiburg` refers now to the individual in the Core Session, while `freiburg_copy` refers to the copy of the individual that has been created in the new session." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As it can be inferred from the fact that the new session contains only one individual, only the _intrinsic_ information about the individual has been transferred, but not the connections to other ontology individuals nor any intrinsic information of the other ontology individuals themselves." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To keep the connection to another ontology individual, it is necessary to transfer **both of them together**." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{, , , , } " ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "session.clear() # this removes all individuals from the session\n", "\n", "copies = session.add(freiburg, neighborhoods) # note that Python iterables of individuals can also be passed to `add` (such as `neighborhoods`)\n", "freiburg_copy = copies[0] # the order in which individuals were added is respected\n", "freiburg_copy.get()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As shown in the example, the [clear](../../api_reference.md#simphony_osp.session.Session.clear) method removes all ontology individuals from a session. The [delete](../../api_reference.md#simphony_osp.session.Session.delete) method allows to exactly select the individuals to remove. Both ontology individuals and identifiers can be passed to [delete](../../api_reference.md#simphony_osp.session.Session.delete)." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "session.delete(freiburg.identifier, copies[1:])\n", "list(session)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A special situation arises when one tries to add an ontology individual to a session that already contains an individual with the same identifier." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "session_A = Session(); session_A.locked = True\n", "with session_A:\n", " lena_A = city.Citizen(name='Lena', age=70,\n", " iri='https://example.org/entities#Lena')\n", "\n", "session_B = Session(); session_B.locked = True\n", "with session_B:\n", " lena_B = city.Citizen(name='Helena', age=31,\n", " iri='https://example.org/entities#Lena')" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [ { "ename": "RuntimeError", "evalue": "Some of the added entities already exist on the session.", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mSession\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0msession\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0msession\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlena_A\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0msession\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlena_B\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# -> Fails, there is already an individual with the same identifier.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m~/Dokumente/SimPhoNy/simphony-osp/simphony_osp/session/session.py\u001b[0m in \u001b[0;36madd\u001b[0;34m(self, merge, exists_ok, all_triples, *individuals)\u001b[0m\n\u001b[1;32m 808\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mexists_ok\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 809\u001b[0m ):\n\u001b[0;32m--> 810\u001b[0;31m raise RuntimeError(\n\u001b[0m\u001b[1;32m 811\u001b[0m \u001b[0;34m\"Some of the added entities already exist on the session.\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 812\u001b[0m )\n", "\u001b[0;31mRuntimeError\u001b[0m: Some of the added entities already exist on the session." ] } ], "source": [ "with Session() as session:\n", " session.add(lena_A)\n", " session.add(lena_B) # -> Fails, there is already an individual with the same identifier." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When this happens, an exception is raised. It is still possible to copy the individual, but is necessary to decide whether:\n", "\n", "- the existing individual should be overwritten (default) or;\n", "- the new individual should be merged with the existing one." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To apply default action (overwrite), use the keyword argument `exists_ok=True`." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "70 Lena\n", "31 Helena\n" ] } ], "source": [ "with Session() as session:\n", " copy = session.add(lena_A)\n", " print(copy.age, copy.name)\n", " copy = session.add(lena_B, exists_ok=True)\n", " print(copy.age, copy.name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Overwriting replaces the classes, attributes, attribute values and connections to other ontology individuals." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To merge the new individual with the previous one, use `exists_ok=True, merge=True` instead." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "70 Lena\n", "{70, 31} {'Helena', 'Lena'}\n" ] } ], "source": [ "with Session() as session:\n", " copy = session.add(lena_A)\n", " print(copy.age, copy.name)\n", " copy = session.add(lena_B, exists_ok=True, merge=True)\n", " print(copy['age'], copy['name'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Merging combines the classes, atrributes, attribute values and connections of the two individuals." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.12" }, "toc-showcode": false, "toc-showtags": true }, "nbformat": 4, "nbformat_minor": 4 }