From 276ddade578500c5d3a67bde18bfe301c06051c1 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 27 Jun 2024 11:36:10 +0200 Subject: [PATCH 01/10] change rshift to matmul and change execution order --- atomrdf/network/term.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/atomrdf/network/term.py b/atomrdf/network/term.py index b914bbb..781919c 100644 --- a/atomrdf/network/term.py +++ b/atomrdf/network/term.py @@ -281,7 +281,8 @@ def __eq__(self, val): """ = """ - # self._is_number(val) + print("eq") + print(f'lhs {self} rhs {val}') self._is_data_node() item = copy.deepcopy(self) item._condition = item._create_condition_string("=", val) @@ -316,6 +317,8 @@ def __ge__(self, val): return item def __gt__(self, val): + print("gt") + print(f'lhs {self} rhs {val}') self._is_number(val) self._is_data_node() item = copy.deepcopy(self) @@ -358,9 +361,11 @@ def __or__(self, term): def or_(self, term): self.__or__(term) - def __rshift__(self, term): - item = copy.deepcopy(term) - item._parents.append(copy.deepcopy(self)) + def __matmul__(self, term): + print("matmul") + print(f'lhs {self} rhs {term}') + item = copy.deepcopy(self) + item._parents.append(copy.deepcopy(term)) return item def refresh_condition(self): From a126d85e33c007e1139472864750506d22a11df2 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 27 Jun 2024 11:38:24 +0200 Subject: [PATCH 02/10] create conditions with variable name instead of query name --- atomrdf/network/term.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomrdf/network/term.py b/atomrdf/network/term.py index 781919c..7815668 100644 --- a/atomrdf/network/term.py +++ b/atomrdf/network/term.py @@ -274,7 +274,7 @@ def _is_data_node(self): def _create_condition_string(self, condition, val): - return f'(?{self.query_name}{condition}"{val}"^^xsd:{self._clean_datatype(self.range[0])})' + return f'(?{self.variable_name}{condition}"{val}"^^xsd:{self._clean_datatype(self.range[0])})' # overloading operators def __eq__(self, val): From dc4d0464bba1cc96418f5b9213f30c2c17b68110 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 27 Jun 2024 12:00:45 +0200 Subject: [PATCH 03/10] test variable name in adding parents --- atomrdf/network/network.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atomrdf/network/network.py b/atomrdf/network/network.py index 89c8e8e..f2aff5e 100644 --- a/atomrdf/network/network.py +++ b/atomrdf/network/network.py @@ -383,7 +383,7 @@ def create_query(self, source, destinations, enforce_types=True): #iterate through the list, if they have condition parents, add them explicitely for destination in destinations: for parent in destination._condition_parents: - if parent.name not in [d.name for d in destinations]: + if parent.variable_name not in [d.variable_name for d in destinations]: destinations.append(parent) #all names are now collected, in a list of lists From caff749475770c6ab752ef3526f15bc57d0b6052 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 27 Jun 2024 12:27:10 +0200 Subject: [PATCH 04/10] fix examples --- examples/01_getting_started.ipynb | 2 +- examples/02_grain_boundaries.ipynb | 2 +- examples/03_point_defects.ipynb | 2 +- examples/05_interstitials.ipynb | 2 +- examples/07_dislocation.ipynb | 2 +- examples/09_structure_modification.ipynb | 2 +- .../03_murnaghan_pyiron.ipynb | 83 +------------------ .../workflow_examples/05_quasiharmonic.ipynb | 2 +- notebooks/semantic_operations.ipynb | 81 +++++++++++++++++- 9 files changed, 88 insertions(+), 90 deletions(-) diff --git a/examples/01_getting_started.ipynb b/examples/01_getting_started.ipynb index 2ae3289..e7d2b94 100644 --- a/examples/01_getting_started.ipynb +++ b/examples/01_getting_started.ipynb @@ -3589,7 +3589,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.1.-1" } }, "nbformat": 4, diff --git a/examples/02_grain_boundaries.ipynb b/examples/02_grain_boundaries.ipynb index 310253e..14622db 100644 --- a/examples/02_grain_boundaries.ipynb +++ b/examples/02_grain_boundaries.ipynb @@ -1617,7 +1617,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.1.-1" } }, "nbformat": 4, diff --git a/examples/03_point_defects.ipynb b/examples/03_point_defects.ipynb index ce86926..9fc12e5 100644 --- a/examples/03_point_defects.ipynb +++ b/examples/03_point_defects.ipynb @@ -5214,7 +5214,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.1.-1" } }, "nbformat": 4, diff --git a/examples/05_interstitials.ipynb b/examples/05_interstitials.ipynb index 3fd8ce3..83dcf53 100644 --- a/examples/05_interstitials.ipynb +++ b/examples/05_interstitials.ipynb @@ -2517,7 +2517,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.1.-1" } }, "nbformat": 4, diff --git a/examples/07_dislocation.ipynb b/examples/07_dislocation.ipynb index b2d4a68..2312eab 100644 --- a/examples/07_dislocation.ipynb +++ b/examples/07_dislocation.ipynb @@ -2733,7 +2733,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.1.-1" } }, "nbformat": 4, diff --git a/examples/09_structure_modification.ipynb b/examples/09_structure_modification.ipynb index 081d94c..e712ca5 100644 --- a/examples/09_structure_modification.ipynb +++ b/examples/09_structure_modification.ipynb @@ -8482,7 +8482,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.1.-1" } }, "nbformat": 4, diff --git a/examples/workflow_examples/03_murnaghan_pyiron.ipynb b/examples/workflow_examples/03_murnaghan_pyiron.ipynb index de43d4c..09ff597 100644 --- a/examples/workflow_examples/03_murnaghan_pyiron.ipynb +++ b/examples/workflow_examples/03_murnaghan_pyiron.ipynb @@ -75,87 +75,6 @@ "kg.enable_workflow(pr, workflow_environment='pyiron')" ] }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "cmso:hasNumberOfAtoms" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "kg.terms.cmso.hasNumberOfAtoms" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "a2\n" - ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
AtomicScaleSamplehasNumberOfAtomsvalue
0sample:410f2be6-9bc8-44bc-8568-25ef67ffe05a2
\n", - "
" - ], - "text/plain": [ - " AtomicScaleSample hasNumberOfAtomsvalue\n", - "0 sample:410f2be6-9bc8-44bc-8568-25ef67ffe05a 2" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "kg.auto_query(kg.terms.cmso.AtomicScaleSample, kg.terms.cmso.hasNumberOfAtoms==2, enforce_types=True)" - ] - }, { "cell_type": "code", "execution_count": 6, @@ -2783,7 +2702,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.1.-1" } }, "nbformat": 4, diff --git a/examples/workflow_examples/05_quasiharmonic.ipynb b/examples/workflow_examples/05_quasiharmonic.ipynb index c02115e..6a2cc0c 100644 --- a/examples/workflow_examples/05_quasiharmonic.ipynb +++ b/examples/workflow_examples/05_quasiharmonic.ipynb @@ -335,7 +335,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.1.-1" } }, "nbformat": 4, diff --git a/notebooks/semantic_operations.ipynb b/notebooks/semantic_operations.ipynb index c13b0b2..ef58b52 100644 --- a/notebooks/semantic_operations.ipynb +++ b/notebooks/semantic_operations.ipynb @@ -341,6 +341,85 @@ "cell_type": "markdown", "metadata": {}, "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "query = \"\"\"\n", + "PREFIX cmso: \n", + "SELECT DISTINCT ?symbol\n", + "WHERE {\n", + " ?sample cmso:hasNumberOfAtoms ?number .\n", + " ?sample cmso:hasMaterial ?material .\n", + " ?material cmso:hasStructure ?structure .\n", + " ?structure cmso:hasSpaceGroupSymbol ?symbol .\n", + "FILTER (?number=\"4\"^^xsd:integer)\n", + "}\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "kg.query_sample([kg.terms.cmso.hasSpaceGroupSymbol, kg.terms.cmso.hasNumberOfAtoms==4])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "res = kg.query_sample( \n", + " [kg.ontology.terms.cmso.hasAltName=='bcc'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "res = kg.query_sample(kg.ontology.terms.pldo.SymmetricalTiltGrainBoundary)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "res = kg.query_sample([kg.ontology.terms.pldo.SymmetricalTiltGrainBoundary, \n", + " kg.ontology.terms.pldo.hasSigmaValue])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "res = kg.query_sample(kg.ontology.terms.ldo.ScrewDislocation)\n" + ] } ], "metadata": { @@ -359,7 +438,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.1.-1" } }, "nbformat": 4, From 27576fbe602604c42f42d65cd54b5361e6d362dc Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 27 Jun 2024 12:27:41 +0200 Subject: [PATCH 05/10] add data notebook --- .../generate_sample_data/generate_data.ipynb | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 notebooks/generate_sample_data/generate_data.ipynb diff --git a/notebooks/generate_sample_data/generate_data.ipynb b/notebooks/generate_sample_data/generate_data.ipynb new file mode 100644 index 0000000..c1f187b --- /dev/null +++ b/notebooks/generate_sample_data/generate_data.ipynb @@ -0,0 +1,224 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Generate dataset\n", + "\n", + "The aim of this notebook is to create a varied dataset with atomRDF that can be used testing quering methods, and also to show to variety of tasks that can be done. This should be runnable top to bottom." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%config IPCompleter.evaluation='unsafe'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a project" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from pyiron_atomistics import Project\n", + "from atomrdf import KnowledgeGraph, System\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "project = 'data_gen_1'\n", + "pr = Project(project)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "kg = KnowledgeGraph(store='db', store_file=f'{project}.db')\n", + "kg.enable_workflow(pr, workflow_environment='pyiron')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Regular structures" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "struct_Fe = System.create.element.Fe(graph=kg)\n", + "struct_Si = System.create.element.Si(graph=kg)\n", + "struct_l12 = System.create.lattice.l12(element=['Al', 'Ni'], \n", + " lattice_constant=3.57, graph=kg)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "struct_gb_1 = System.create.defect.grain_boundary(axis=[0,0,1], \n", + " sigma=5, \n", + " gb_plane=[3, -1, 0],\n", + " element='Fe',\n", + " graph=kg)\n", + "struct_gb_2 = System.create.defect.grain_boundary(axis=[1,1,1], \n", + " sigma=19, \n", + " gb_plane=[-3, 2, 0],\n", + " element='Fe',\n", + " graph=kg)\n", + "\n", + "struct_gb_3 = System.create.defect.grain_boundary(axis=[1,1,1], \n", + " sigma=19, \n", + " gb_plane=[-1, -1, -1],\n", + " element='Fe',\n", + " graph=kg)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "struct_Fe = System.create.element.Fe(graph=kg)\n", + "struct_with_vacancy = struct_Fe.delete(indices=[0], copy_structure=True)\n", + "struct_Al = System.create.element.Al(graph=kg)\n", + "struct_Al.substitute_atoms('Mg', indices=[0], copy_structure=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "slip_direction = np.array([1, 0, -1])\n", + "slip_plane = np.array([1, 1, 1])\n", + "slip_system = [slip_direction, slip_plane]\n", + "burgers_vector = 0.5\n", + "dislocation_line = np.array([1, 0, -1])\n", + "elastic_constant_dict = {'C11': 169, 'C12': 122, 'C44': 75.4}\n", + "sys = System.create.defect.dislocation(slip_system,\n", + " dislocation_line,\n", + " elastic_constant_dict,\n", + " burgers_vector=burgers_vector,\n", + " element='Cu',\n", + " dislocation_type='monopole',\n", + " graph=kg,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "structure = pr.create.structure.annotated_structure.bulk('Cu', cubic=True)\n", + "job = pr.create.job.Lammps('j1', delete_existing_job=True, delete_aborted_job=True)\n", + "job.structure = structure\n", + "job.potential = '2001--Mishin-Y--Cu-1--LAMMPS--ipr1'\n", + "job.calc_md(pressure=0, temperature=500)\n", + "job.run()\n", + "kg.add_workflow(job, workflow_environment='pyiron')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "structure = pr.create.structure.annotated_structure.bulk('Cu', cubic=True)\n", + "ref_job = pr.create.job.Lammps('j1', delete_existing_job=True, delete_aborted_job=True)\n", + "ref_job.structure = structure\n", + "ref_job.potential = '2001--Mishin-Y--Cu-1--LAMMPS--ipr1'\n", + "ref_job.calc_minimize()\n", + "murn_job = ref_job.create_job(pr.job_type.Murnaghan, 'murn_job')\n", + "murn_job.input[\"num_points\"] = 5\n", + "murn_job.run()\n", + "kg.add_workflow(murn_job, workflow_environment='pyiron', add_intermediate_jobs=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "struct = pr.create.structure.annotated_structure.bulk('Cu')\n", + "refjob = pr.create.job.Lammps('reflmp')\n", + "refjob.structure = struct\n", + "refjob.potential = '2009--Mendelev-M-I--Cu-Zr--LAMMPS--ipr1'\n", + "phono = pr.create.job.PhonopyJob('phono')\n", + "phono.ref_job = refjob\n", + "quasi = pr.create.job.QuasiHarmonicJob('quasi')\n", + "quasi.ref_job = phono\n", + "quasi.input[\"temperature_end\"] = 500\n", + "quasi.input[\"temperature_steps\"] = 2\n", + "quasi.input[\"axes\"]=[\"x\",\"y\",\"z\"]\n", + "quasi.input[\"strains\"] = None\n", + "quasi.run()\n", + "kg.add_workflow(quasi, workflow_environment='pyiron')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "workflow-rdf", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 3f888da36fec2f5295c730d2b0470df2fb81d980 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 27 Jun 2024 12:47:31 +0200 Subject: [PATCH 06/10] update generate data file --- .../generate_sample_data/generate_data.ipynb | 111 ++++++++++++++---- 1 file changed, 89 insertions(+), 22 deletions(-) diff --git a/notebooks/generate_sample_data/generate_data.ipynb b/notebooks/generate_sample_data/generate_data.ipynb index c1f187b..48fa781 100644 --- a/notebooks/generate_sample_data/generate_data.ipynb +++ b/notebooks/generate_sample_data/generate_data.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -27,7 +27,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -38,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -48,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -65,7 +65,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -77,7 +77,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -101,9 +101,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "struct_Fe = System.create.element.Fe(graph=kg)\n", "struct_with_vacancy = struct_Fe.delete(indices=[0], copy_structure=True)\n", @@ -113,7 +124,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -135,9 +146,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The job j1 was saved and received the ID: 1106\n" + ] + } + ], "source": [ "structure = pr.create.structure.annotated_structure.bulk('Cu', cubic=True)\n", "job = pr.create.job.Lammps('j1', delete_existing_job=True, delete_aborted_job=True)\n", @@ -150,9 +169,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The job murn_job was saved and received the ID: 1106\n", + "The job murn_job_0_9 was saved and received the ID: 1107\n", + "The job murn_job_0_95 was saved and received the ID: 1108\n", + "The job murn_job_1_0 was saved and received the ID: 1109\n", + "The job murn_job_1_05 was saved and received the ID: 1110\n", + "The job murn_job_1_1 was saved and received the ID: 1111\n" + ] + } + ], "source": [ "structure = pr.create.structure.annotated_structure.bulk('Cu', cubic=True)\n", "ref_job = pr.create.job.Lammps('j1', delete_existing_job=True, delete_aborted_job=True)\n", @@ -167,9 +199,47 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The job quasi was saved and received the ID: 1112\n", + "The job quasi_0_9 was saved and received the ID: 1113\n", + "The job reflmp_0 was saved and received the ID: 1114\n", + "The job quasi_0_92 was saved and received the ID: 1115\n", + "The job reflmp_0 was saved and received the ID: 1116\n", + "The job quasi_0_94 was saved and received the ID: 1117\n", + "The job reflmp_0 was saved and received the ID: 1118\n", + "The job quasi_0_96 was saved and received the ID: 1119\n", + "The job reflmp_0 was saved and received the ID: 1120\n", + "The job quasi_0_98 was saved and received the ID: 1121\n", + "The job reflmp_0 was saved and received the ID: 1122\n", + "The job quasi_1_0 was saved and received the ID: 1123\n", + "The job reflmp_0 was saved and received the ID: 1124\n", + "The job quasi_1_02 was saved and received the ID: 1125\n", + "The job reflmp_0 was saved and received the ID: 1126\n", + "The job quasi_1_04 was saved and received the ID: 1127\n", + "The job reflmp_0 was saved and received the ID: 1128\n", + "The job quasi_1_06 was saved and received the ID: 1129\n", + "The job reflmp_0 was saved and received the ID: 1130\n", + "The job quasi_1_08 was saved and received the ID: 1131\n", + "The job reflmp_0 was saved and received the ID: 1132\n", + "The job quasi_1_1 was saved and received the ID: 1133\n", + "The job reflmp_0 was saved and received the ID: 1134\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/srmnitc/miniconda3/envs/workflow-rdf/lib/python3.11/site-packages/atomrdf/graph.py:376: UserWarning: asmo:hasValue has a range with unspecified datatype!\n", + " warnings.warn(f\"{triple[1].name} has a range with unspecified datatype!\")\n" + ] + } + ], "source": [ "struct = pr.create.structure.annotated_structure.bulk('Cu')\n", "refjob = pr.create.job.Lammps('reflmp')\n", @@ -189,15 +259,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": {}, "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] + "source": [ + "kg.archive('dataset')" + ] } ], "metadata": { From 870c18c0a5874fe8a4fed5cfabd750c97aac8622 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 27 Jun 2024 14:11:21 +0200 Subject: [PATCH 07/10] remove prints in term --- atomrdf/network/term.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/atomrdf/network/term.py b/atomrdf/network/term.py index 7815668..a852dd0 100644 --- a/atomrdf/network/term.py +++ b/atomrdf/network/term.py @@ -281,8 +281,8 @@ def __eq__(self, val): """ = """ - print("eq") - print(f'lhs {self} rhs {val}') + #print("eq") + #print(f'lhs {self} rhs {val}') self._is_data_node() item = copy.deepcopy(self) item._condition = item._create_condition_string("=", val) @@ -317,8 +317,8 @@ def __ge__(self, val): return item def __gt__(self, val): - print("gt") - print(f'lhs {self} rhs {val}') + #print("gt") + #print(f'lhs {self} rhs {val}') self._is_number(val) self._is_data_node() item = copy.deepcopy(self) @@ -362,8 +362,8 @@ def or_(self, term): self.__or__(term) def __matmul__(self, term): - print("matmul") - print(f'lhs {self} rhs {term}') + #print("matmul") + #print(f'lhs {self} rhs {term}') item = copy.deepcopy(self) item._parents.append(copy.deepcopy(term)) return item From b244ac7f7308fafad3e4a8ece86473db23615eb4 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 27 Jun 2024 14:56:57 +0200 Subject: [PATCH 08/10] add query tutorial --- atomrdf/network/ontology.py | 1 + examples/10_sparql_queries.ipynb | 1160 ++++++++++++++++++++++++++++++ examples/dataset.tar.gz | Bin 0 -> 42889 bytes 3 files changed, 1161 insertions(+) create mode 100644 examples/10_sparql_queries.ipynb create mode 100644 examples/dataset.tar.gz diff --git a/atomrdf/network/ontology.py b/atomrdf/network/ontology.py index f96317f..30bd71c 100644 --- a/atomrdf/network/ontology.py +++ b/atomrdf/network/ontology.py @@ -134,5 +134,6 @@ def read_ontology(): combo.add_path(("asmo:InteratomicPotential", "cmso:hasReference", "string")) combo.add_path(("asmo:InteratomicPotential", "rdfs:label", "string")) + # return return combo diff --git a/examples/10_sparql_queries.ipynb b/examples/10_sparql_queries.ipynb new file mode 100644 index 0000000..0ea5606 --- /dev/null +++ b/examples/10_sparql_queries.ipynb @@ -0,0 +1,1160 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# SPARQL queries\n", + "\n", + "This notebook demonstrates how SPARQL queries can be composed programmatically, and without (almost) no knowledge of SPARQL. For this purpose, we will use an existing dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f91e78cb67cf4f979fbad1022ea5c6fa", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from atomrdf import KnowledgeGraph" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "kg = KnowledgeGraph.unarchive('dataset.tar.gz')" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "22" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.n_samples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The dataset contains 22 samples" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Of course, SPARQL queries can be directly run through atomRDF. See an example:" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "query = \"\"\"\n", + "PREFIX cmso: \n", + "SELECT DISTINCT ?sample ?symbol ?number \n", + "WHERE {\n", + " ?sample cmso:hasMaterial ?material .\n", + " ?material cmso:hasStructure ?structure .\n", + " ?structure cmso:hasSpaceGroupSymbol ?symbol .\n", + " ?sample cmso:hasNumberOfAtoms ?number .\n", + "FILTER (?number=\"4\"^^xsd:integer)\n", + "}\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The above query finds the Space Group symbol of all structures which have four atoms." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
samplesymbolnumber
0sample:10ffd2cc-9e92-4f04-896d-d6c0fdb9e55fPm-3m4
1sample:1f6b1b0f-446a-4ad8-877e-d2e6176797dfFm-3m4
2sample:286c3974-962b-4333-a2bb-d164ae645454Fm-3m4
3sample:67be61c7-f9c7-4d46-a61d-5350fd0ee246Fm-3m4
4sample:721b7447-8363-4e65-9515-9da2581d7124Fm-3m4
5sample:8fc8e47b-acee-40f8-bcbf-fc298cc31f05Fm-3m4
6sample:9f0f48d1-5ebf-4f7a-b241-5e7aa273f5a0Fm-3m4
7sample:a3cf6d97-c922-4c4d-8517-e784df83b71eFm-3m4
8sample:ab2bea57-39ea-49ea-ad3f-c1c40b013154Fm-3m4
9sample:aef7472e-7577-4256-8422-6ba77a954ce1Fm-3m4
10sample:b1f52dc6-5c92-428f-8f7a-78794fd0544cFm-3m4
11sample:d015cfca-e047-40bc-baab-423e87fa2618Fm-3m4
12sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2eFm-3m4
13sample:fb01a7f2-8984-442b-a32e-15321c4fa99bFm-3m4
\n", + "
" + ], + "text/plain": [ + " sample symbol number\n", + "0 sample:10ffd2cc-9e92-4f04-896d-d6c0fdb9e55f Pm-3m 4\n", + "1 sample:1f6b1b0f-446a-4ad8-877e-d2e6176797df Fm-3m 4\n", + "2 sample:286c3974-962b-4333-a2bb-d164ae645454 Fm-3m 4\n", + "3 sample:67be61c7-f9c7-4d46-a61d-5350fd0ee246 Fm-3m 4\n", + "4 sample:721b7447-8363-4e65-9515-9da2581d7124 Fm-3m 4\n", + "5 sample:8fc8e47b-acee-40f8-bcbf-fc298cc31f05 Fm-3m 4\n", + "6 sample:9f0f48d1-5ebf-4f7a-b241-5e7aa273f5a0 Fm-3m 4\n", + "7 sample:a3cf6d97-c922-4c4d-8517-e784df83b71e Fm-3m 4\n", + "8 sample:ab2bea57-39ea-49ea-ad3f-c1c40b013154 Fm-3m 4\n", + "9 sample:aef7472e-7577-4256-8422-6ba77a954ce1 Fm-3m 4\n", + "10 sample:b1f52dc6-5c92-428f-8f7a-78794fd0544c Fm-3m 4\n", + "11 sample:d015cfca-e047-40bc-baab-423e87fa2618 Fm-3m 4\n", + "12 sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2e Fm-3m 4\n", + "13 sample:fb01a7f2-8984-442b-a32e-15321c4fa99b Fm-3m 4" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.query(query)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The results are given in the form of a Pandas DataFrame." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This query can also be performed programmatically, which looks like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
AtomicScaleSamplehasSpaceGroupSymbolvaluehasNumberOfAtomsvalue
0sample:10ffd2cc-9e92-4f04-896d-d6c0fdb9e55fPm-3m4
1sample:286c3974-962b-4333-a2bb-d164ae645454Fm-3m4
2sample:8fc8e47b-acee-40f8-bcbf-fc298cc31f05Fm-3m4
3sample:9f0f48d1-5ebf-4f7a-b241-5e7aa273f5a0Fm-3m4
4sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2eFm-3m4
5sample:1f6b1b0f-446a-4ad8-877e-d2e6176797dfFm-3m4
6sample:67be61c7-f9c7-4d46-a61d-5350fd0ee246Fm-3m4
7sample:721b7447-8363-4e65-9515-9da2581d7124Fm-3m4
8sample:a3cf6d97-c922-4c4d-8517-e784df83b71eFm-3m4
9sample:ab2bea57-39ea-49ea-ad3f-c1c40b013154Fm-3m4
10sample:b1f52dc6-5c92-428f-8f7a-78794fd0544cFm-3m4
11sample:d015cfca-e047-40bc-baab-423e87fa2618Fm-3m4
12sample:fb01a7f2-8984-442b-a32e-15321c4fa99bFm-3m4
13sample:aef7472e-7577-4256-8422-6ba77a954ce1Fm-3m4
\n", + "
" + ], + "text/plain": [ + " AtomicScaleSample hasSpaceGroupSymbolvalue \\\n", + "0 sample:10ffd2cc-9e92-4f04-896d-d6c0fdb9e55f Pm-3m \n", + "1 sample:286c3974-962b-4333-a2bb-d164ae645454 Fm-3m \n", + "2 sample:8fc8e47b-acee-40f8-bcbf-fc298cc31f05 Fm-3m \n", + "3 sample:9f0f48d1-5ebf-4f7a-b241-5e7aa273f5a0 Fm-3m \n", + "4 sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2e Fm-3m \n", + "5 sample:1f6b1b0f-446a-4ad8-877e-d2e6176797df Fm-3m \n", + "6 sample:67be61c7-f9c7-4d46-a61d-5350fd0ee246 Fm-3m \n", + "7 sample:721b7447-8363-4e65-9515-9da2581d7124 Fm-3m \n", + "8 sample:a3cf6d97-c922-4c4d-8517-e784df83b71e Fm-3m \n", + "9 sample:ab2bea57-39ea-49ea-ad3f-c1c40b013154 Fm-3m \n", + "10 sample:b1f52dc6-5c92-428f-8f7a-78794fd0544c Fm-3m \n", + "11 sample:d015cfca-e047-40bc-baab-423e87fa2618 Fm-3m \n", + "12 sample:fb01a7f2-8984-442b-a32e-15321c4fa99b Fm-3m \n", + "13 sample:aef7472e-7577-4256-8422-6ba77a954ce1 Fm-3m \n", + "\n", + " hasNumberOfAtomsvalue \n", + "0 4 \n", + "1 4 \n", + "2 4 \n", + "3 4 \n", + "4 4 \n", + "5 4 \n", + "6 4 \n", + "7 4 \n", + "8 4 \n", + "9 4 \n", + "10 4 \n", + "11 4 \n", + "12 4 \n", + "13 4 " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.query_sample([kg.terms.cmso.hasSpaceGroupSymbol, kg.terms.cmso.hasNumberOfAtoms==4])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or more explicitely (`query_sample` is just a shortcut for `auto_query`)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
AtomicScaleSamplehasSpaceGroupSymbolvaluehasNumberOfAtomsvalue
0sample:10ffd2cc-9e92-4f04-896d-d6c0fdb9e55fPm-3m4
1sample:286c3974-962b-4333-a2bb-d164ae645454Fm-3m4
2sample:8fc8e47b-acee-40f8-bcbf-fc298cc31f05Fm-3m4
3sample:9f0f48d1-5ebf-4f7a-b241-5e7aa273f5a0Fm-3m4
4sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2eFm-3m4
5sample:1f6b1b0f-446a-4ad8-877e-d2e6176797dfFm-3m4
6sample:67be61c7-f9c7-4d46-a61d-5350fd0ee246Fm-3m4
7sample:721b7447-8363-4e65-9515-9da2581d7124Fm-3m4
8sample:a3cf6d97-c922-4c4d-8517-e784df83b71eFm-3m4
9sample:ab2bea57-39ea-49ea-ad3f-c1c40b013154Fm-3m4
10sample:b1f52dc6-5c92-428f-8f7a-78794fd0544cFm-3m4
11sample:d015cfca-e047-40bc-baab-423e87fa2618Fm-3m4
12sample:fb01a7f2-8984-442b-a32e-15321c4fa99bFm-3m4
13sample:aef7472e-7577-4256-8422-6ba77a954ce1Fm-3m4
\n", + "
" + ], + "text/plain": [ + " AtomicScaleSample hasSpaceGroupSymbolvalue \\\n", + "0 sample:10ffd2cc-9e92-4f04-896d-d6c0fdb9e55f Pm-3m \n", + "1 sample:286c3974-962b-4333-a2bb-d164ae645454 Fm-3m \n", + "2 sample:8fc8e47b-acee-40f8-bcbf-fc298cc31f05 Fm-3m \n", + "3 sample:9f0f48d1-5ebf-4f7a-b241-5e7aa273f5a0 Fm-3m \n", + "4 sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2e Fm-3m \n", + "5 sample:1f6b1b0f-446a-4ad8-877e-d2e6176797df Fm-3m \n", + "6 sample:67be61c7-f9c7-4d46-a61d-5350fd0ee246 Fm-3m \n", + "7 sample:721b7447-8363-4e65-9515-9da2581d7124 Fm-3m \n", + "8 sample:a3cf6d97-c922-4c4d-8517-e784df83b71e Fm-3m \n", + "9 sample:ab2bea57-39ea-49ea-ad3f-c1c40b013154 Fm-3m \n", + "10 sample:b1f52dc6-5c92-428f-8f7a-78794fd0544c Fm-3m \n", + "11 sample:d015cfca-e047-40bc-baab-423e87fa2618 Fm-3m \n", + "12 sample:fb01a7f2-8984-442b-a32e-15321c4fa99b Fm-3m \n", + "13 sample:aef7472e-7577-4256-8422-6ba77a954ce1 Fm-3m \n", + "\n", + " hasNumberOfAtomsvalue \n", + "0 4 \n", + "1 4 \n", + "2 4 \n", + "3 4 \n", + "4 4 \n", + "5 4 \n", + "6 4 \n", + "7 4 \n", + "8 4 \n", + "9 4 \n", + "10 4 \n", + "11 4 \n", + "12 4 \n", + "13 4 " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.auto_query(kg.terms.cmso.AtomicScaleSample, [kg.terms.cmso.hasSpaceGroupSymbol, kg.terms.cmso.hasNumberOfAtoms==4])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now the building of such a query programmatically is discussed. The function needs a source and destination(s). Destination can include conditions attached to it, for example, that numbers of atoms. The first thing to do is to find the right terms. For this, we can use the tab completion feature." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "cmso, qudt, pldo, podo, asmo, ns, calculation, ldo, prov, rdf, rdfs" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.terms" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Those are all the ontologies, with the terms we use. One can go deeper down" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "SimulationCell, UnitCell, LatticeAngle, SimulationCellAngle, Angle, AtomicScaleSample, AtomicForce, AtomicPosition, AtomicVelocity, CoordinationNumber, Occupancy, AtomAttribute, Basis, MacroscaleSample, MesoscaleSample, MicroscaleSample, NanoscaleSample, ComputationalSample, CalculatedProperty, CrystallineMaterial, CrystalDefect, Atom, Molecule, ChemicalSpecies, ChemicalElement, LatticeParameter, SimulationCellLength, Length, AmorphousMaterial, Material, CrystalStructure, SpaceGroup, Microstructure, Structure, LatticeVector, SimulationCellVector, Vector, ChemicalComposition, hasAngle, hasAttribute, hasBasis, hasCalculatedProperty, isCalculatedPropertyOf, hasDefect, isDefectOf, hasElement, hasLatticeParameter, hasLength, hasMaterial, isMaterialOf, hasSimulationCell, hasSpaceGroup, hasSpecies, hasStructure, hasUnit, hasUnitCell, hasVector, hasAltName, hasName, hasAngle_alpha, hasAngle_beta, hasAngle_gamma, hasAtomicPercent, hasBravaisLattice, hasChemicalSymbol, hasSymbol, hasComponent_x, hasComponent_y, hasComponent_z, hasElementRatio, hasIdentifier, hasLength_x, hasLength_y, hasLength_z, hasNumberOfAtoms, hasPath, hasReference, hasRepetition_x, hasRepetition_y, hasRepetition_z, hasSpaceGroupNumber, hasSpaceGroupSymbol, hasValue, hasVolume, hasWeightPercent" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.terms.cmso" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And further select terms from there." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "cmso:AtomicScaleSample" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.terms.cmso.AtomicScaleSample" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Applying constraints can be done through basic comparison operators" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic comparison operations\n", + "\n", + "Basic operators such as <, >, <=, >=, and ==" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These operations are useful for adding conditions to the SPARQL query. When these operations are performed on a term, it is stored in its condition string. No other changes are needed. " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "cmso:hasElementRatio" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.terms.cmso.hasElementRatio==1.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Logical operators\n", + "\n", + "Logical operators currently supported are & and ||. These operators, when applied, aggregates the condition between two terms|" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "cmso:hasChemicalSymbol" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(kg.terms.cmso.hasChemicalSymbol=='Al') & (kg.terms.cmso.hasElementRatio==1.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## @ operator\n", + "\n", + "The final class of operator we have is the @ operator. This can be used for resolving terms that has multiple paths. For example, rdfs:label which multiple entities can have. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we want to specify label for the InputParameter, it can be done like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "rdfs:label" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.terms.rdfs.label@kg.terms.asmo.hasInputParameter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "conditions can also be applied on top" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "rdfs:label" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.terms.rdfs.label@kg.terms.asmo.hasInputParameter=='label_string'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "That summarises all the possible options. Now we put together these blocks to formulate some more complex queries" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__All samples that have been used for an energy calculation__" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
AtomicScaleSampleEnergyCalculation
0sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2eactivity:f61a2139-2dae-4aab-954e-73d34d7bc042
1sample:721b7447-8363-4e65-9515-9da2581d7124activity:0848b931-d647-41c7-a6dc-8150989e36c7
2sample:ab2bea57-39ea-49ea-ad3f-c1c40b013154activity:8a680cb2-c7f1-4747-95b0-a4ce71fab87f
3sample:b1f52dc6-5c92-428f-8f7a-78794fd0544cactivity:2e461195-15a4-45ba-b369-5a2429ded084
4sample:d015cfca-e047-40bc-baab-423e87fa2618activity:1e081e86-73fd-45e5-8341-cab787b9ff0c
5sample:fb01a7f2-8984-442b-a32e-15321c4fa99bactivity:923e1808-efdf-4a6a-a5de-9e0a64cb198c
\n", + "
" + ], + "text/plain": [ + " AtomicScaleSample \\\n", + "0 sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2e \n", + "1 sample:721b7447-8363-4e65-9515-9da2581d7124 \n", + "2 sample:ab2bea57-39ea-49ea-ad3f-c1c40b013154 \n", + "3 sample:b1f52dc6-5c92-428f-8f7a-78794fd0544c \n", + "4 sample:d015cfca-e047-40bc-baab-423e87fa2618 \n", + "5 sample:fb01a7f2-8984-442b-a32e-15321c4fa99b \n", + "\n", + " EnergyCalculation \n", + "0 activity:f61a2139-2dae-4aab-954e-73d34d7bc042 \n", + "1 activity:0848b931-d647-41c7-a6dc-8150989e36c7 \n", + "2 activity:8a680cb2-c7f1-4747-95b0-a4ce71fab87f \n", + "3 activity:2e461195-15a4-45ba-b369-5a2429ded084 \n", + "4 activity:1e081e86-73fd-45e5-8341-cab787b9ff0c \n", + "5 activity:923e1808-efdf-4a6a-a5de-9e0a64cb198c " + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.auto_query(kg.terms.cmso.AtomicScaleSample, kg.terms.asmo.EnergyCalculation)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "__Which of those had an input parameter, called Temperature?__" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
AtomicScaleSampleEnergyCalculationInputParameter_labelvalue
0sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2eactivity:f61a2139-2dae-4aab-954e-73d34d7bc042temperature
\n", + "
" + ], + "text/plain": [ + " AtomicScaleSample \\\n", + "0 sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2e \n", + "\n", + " EnergyCalculation InputParameter_labelvalue \n", + "0 activity:f61a2139-2dae-4aab-954e-73d34d7bc042 temperature " + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.auto_query(kg.terms.cmso.AtomicScaleSample, [kg.terms.asmo.EnergyCalculation,\n", + " kg.terms.rdfs.label@kg.terms.asmo.InputParameter=='temperature'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And the value" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
AtomicScaleSampleEnergyCalculationInputParameter_labelvalueInputParameter_hasValuevalue
0sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2eactivity:f61a2139-2dae-4aab-954e-73d34d7bc042temperature500.0
\n", + "
" + ], + "text/plain": [ + " AtomicScaleSample \\\n", + "0 sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2e \n", + "\n", + " EnergyCalculation InputParameter_labelvalue \\\n", + "0 activity:f61a2139-2dae-4aab-954e-73d34d7bc042 temperature \n", + "\n", + " InputParameter_hasValuevalue \n", + "0 500.0 " + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.auto_query(kg.terms.cmso.AtomicScaleSample, [kg.terms.asmo.EnergyCalculation,\n", + " kg.terms.rdfs.label@kg.terms.asmo.InputParameter=='temperature',\n", + " kg.terms.asmo.hasValue@kg.terms.asmo.InputParameter])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**What is the composition and space group of these structures**" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
AtomicScaleSampleInputParameter_labelvalueInputParameter_hasValuevaluehasSpaceGroupSymbolvaluehasChemicalSymbolvaluehasElementRatiovalue
0sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2etemperature500.0Fm-3mCu1.0
\n", + "
" + ], + "text/plain": [ + " AtomicScaleSample InputParameter_labelvalue \\\n", + "0 sample:e54c0e91-52ec-4c47-8ba3-43979a1ebe2e temperature \n", + "\n", + " InputParameter_hasValuevalue hasSpaceGroupSymbolvalue \\\n", + "0 500.0 Fm-3m \n", + "\n", + " hasChemicalSymbolvalue hasElementRatiovalue \n", + "0 Cu 1.0 " + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "kg.auto_query(kg.terms.cmso.AtomicScaleSample, [\n", + " kg.terms.rdfs.label@kg.terms.asmo.InputParameter=='temperature',\n", + " kg.terms.asmo.hasValue@kg.terms.asmo.InputParameter,\n", + " kg.terms.cmso.hasSpaceGroupSymbol,\n", + " kg.terms.cmso.hasChemicalSymbol,\n", + " kg.terms.cmso.hasElementRatio])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.11.8" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/dataset.tar.gz b/examples/dataset.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..9fdfeb01830df02c8d5a3abe2687a5c51777ad5e GIT binary patch literal 42889 zcmV)(K#RX0iwFq#Kz(Kc|72lwVRL14E_7jX0PMZnu4`A49jIr2g`nr+%6Y#SFyMv( z!!O-1(2ohjAi2qgjJy;irBOg3|GmdpB+uD<#t7;hmr|8gqB21p?X!ci*1W`J%!o0! z-)+D9&;R}SPyg+5e7pSc&EMpoaQnymcL+Iu{xg3bLyGa6Z~y6=U*Vs>{P@%H2dMw% zxA{-%-~REZ@BeuDPqD{YMrk!~t<2u?fB5G0&%ghF-i|*Vf4uzkyT7FlZtC7U{~db` z@BjU2&&SeoPbK8qu>VsH*#Gs{-2XrR@W(%W|I^w1y`TI0f203we;4+@So@z|_WxJ0 z|HInb~%)G?1$r}oe$SzZLOT@rG>ctuOI*Xr+=aS zuRXuB|M{DcO0L-d;n&>%zft@D&)>a`2Qj*9Lm6-M#H4n>nLH4-by}y_aDFg z=kNaa@ehBw;7`B*eb~Z3eEazLAOG;}@8gzhumAAv$A9y0($*t>aR1l+*UJ`q!hb&g zZGL_K?)}gF;phK)_rs5}kMDZ_Fdw!25B$}4e>k2lf50nz_m6-6@%x{?|MQ=|`zwCh zY8mx-4Tp5j?NF|lb~x6{kM=)*a@+U6`Sip0 z|9unp{qkEnmI3d3I9-q7P%h;SD={4px%4?t$4e|}^~?X)ALw)cpYK0>{yqEOm;ZnH z|Gzi?KW7Ld^_Tzut^5CLJH=CgD?sjlD95*P7` z=nK#P$6;2ahpo+Pt)~&@rT-%Nf9R(EFTMQ#ujKz{x}GlS?RaRj!2e&b1fMExsLUuHpI?E|*l=-|GCoz3TsdCI27$ z`Et5k&xg0kQ=Zc`9p?Fx564q%*ULa8*1w?sZ-meFfB5se`oH~eKK=0hfBzi*k5!To z4jl0)N5r3bA~G52d^lh8+wpCbw`-nDobX@%!Z>01e8mhe|Nrv;U+Vw!M&q2@tN!n| z?*Ds=r(Q}w47lS%xwMM>KjP!-Bnk4MaM@A2AO$|vdn(^e{0Nbc~-rPiAJG~aXpVq>8Hc-d_n#duH$ez zpRR}NIn8lC=XeeE7wP|xaq<5(#Fzj7mHdA@9otC9>*0I~fklAq@~Hg)pFB=)sn${Z zm*oF&rhOC`keM-i@4$eMfAIksSY`CDf7x&T9GXzyj@Mk@!lAdqI0q5WoLJ5A`j#1j zT#xZLh$g(w|6k|-EB>Df1NWEv|E>G~nG(Ezhr>@tBsxqAVfW^t^o~rZeq6fjexJ8gXUYLHHb#$~ znRVStXY~*kMaZe=fB3d<2^J*FHMg9~1KNP~wau=UncAg8b#MVL?Dmo;jvo z%KqyyZb(lu)@Ca?%rKLyYSua{o-kuMjgh`e7BACdYpozWMSRr%;oG^@J}apyYR?6K z;E!^jq1K3v(n3h-#!QrZm?MocVNb&#pn(x@B|_W>EZ_}u+Xo9ThoNg})Y)47&|Ca zHf(N0k}=`QiK{r$n5KcbsCe^6+&Kx^>dLYRxut~F!37nmIBhj?0y+kf$mQ5yh21S< z;yr36-gBF%8hf5lk?^ghP`GUfJ!+mUvIYqQ?r4tNgz8*pPgu(#rZ1Dd7t2&QSm?#C z)-iWJjIv?2JD(BLU-7rzLx&Cj$%Qay;WD0W*G%7yaJY|#u-JX$yu~u0vtuELff4>1 z;j*<61LkAS)Zhc0o%;y!5l&zwVM$JGAN)9d%?^q@fWT_N_MNp&u^5{k+`Ns6?T!qR zBbig>#DpzJY#a3-w%W=+J$mRsu>YBPdVoWn}1NTtbmo+vl2pFQ- zBen&%vtzC%-?q}GVyH?Rgi|?5Fh3Zq#@8*5aNe*4bE9m5GQ8ne3Bx?+9jJ=6R+ta2 zM%cbF21Yv#JakI#@)|Xd-G$N2Vh~9ZhnR!II(9HPch|}WSkiR+?{aI7S#7Y>A0w zu`h*>6FgnFP-06JdyxLOwee-LchLdS!8hhC)1y?_l)5jqf*FBD^Y=epAZ8m2vU66s zlOWjJ99TAuSeI{_VU$yV|Aqjbr}eK8##rUt2Q&wWW5B;;3qK4s91(0Sj3tbJfIs}Y zodj^v6n~&2h6Ov0=Qb1mzkkij!d7Y= zC%8WZ4|vi1g}NzRw~)Ck=Wc5QhwDq$$NiNtSlIt~c8qtIu^kKyECNgnf=Co!^; zP9I?i!qUo!lvCC3l|hK$@SXTItcU`AGJbX67`p}w4mJaSl}q`m!R>`n^WXx&=Gmjj zpVwU4-8?o7Rf&iLOM*v9I&zlpjFpIm1jCF~1EZ65*epe{_3)qwja%e|>@kuEn>|@< z&VHyW%DB5v+ISiIYGG(e#3W&dYePnwzCt!2+JMnbtwVEcu{v9~ z+}(UhNTLuZ!jaS-ziR(rK-*{pQ810A>ZsWf-cQL9VlZ(e>4T13y|K+)N0?Y92nhVY zW<6m8;khz?3`>bgtzV-Vi*ZEw7&^YbAL)P1n#kJ>VX_Mmz7!^5bY@$5nDE?42eHP#ZnR-7u*O>DMj}4(1&SXgn!$P-ITH#>DeB1C z*%&Yw3|^2h;MYdf;jd$6u?h-8P&^5iT>2_eB==a4upAij=7cxip1_hsb`)t)F-d_N zK!m@JM}qgopf(o%1f&{YBZ_$~SdcKyh#Md;LnHmracjirFd4Mbbzi_D{PoN;lAB5w z4(kks{VQZ)i!0VMtVd;%f;ax6ef+T25Kaj783JI2>AJpRH`UNPHxq33VA!OiXGgdr z6bxKliQwptGKv`18|^(xf)RmzMH+l_Dqp(5SRsPoVorFP$UNd}REMq5!{mZ(g@`BB z_@%4lNr!ohr+6&k0Ml?jlvv~8gt%{~jKibi$&P(J+TBlcUmyQ2KVAj@ulm2&`TzfM z{of4>dKCct=Fk7H;abL9Jk-nSdMMX^Je*SDfA-@s^?a?z@XPoAHJ<<1_`3h+S33Vc zUt8BE z1*_GVaN$zPWaZ_dw#CoS|^O>rfKw=+Pn?m=jqj>g)xbHAy2wZ=VRjZ zG>a#>f4ehaVx}LVWvr37<35mOR_|#(4e)K`@XjSq8l~F^Jtj;q95c@Q?|xhdX-@B( zKXGEohZRG8pJcTb4lKbVWEvA}B#RF&hcKUStIyxWYyCnm(R-%)OvMuI-{n%OInPm^ zFFy4M{(yg81p%Kt+4-5}C!R)3QGT2??msFsVw!$-?Wt#x^K(CjxQ{;uw6ei?U3o&i zw+TPJYHIj@`#JL_RQp@-^EVWh`=)o)ZDP#Clc?>tKgQ=5$)OSBca2+(@=2bV{Lep( z71p4qXI^K0lJU&mi*NQUxSy@&d_hWz7-=5sC!Hv8c`Q#zD$c{_|6`{B~by*Bcx$ICB||Fi#} z%|x&K|JTX?(<#*6&*PBh8F5QR@N&GCf(YgqQ$Jl}AMsxY|F2_=*5A&D#;Yew#QHm( z5|-ojJde4>>v>#X`2W8L|NrX$|5x+>g8#oxHe|ir|I7bh;~TQp!`r1E4`p1hhY`-@ zaJ}YoWnO&g|8oA{jK8Ud|F^~d^8de%{}1UjXYBC$HJlISdMSrvM9_Dv$G6k@n#1uj z*ZY6Q)&pzaGuwRj_7*mA%o^D*lhaLNDTW@<$W{#vJU{hsF+pXUMUzu}i zw_;uBf!r8p5#PGYjuz2OXO*W8~TxYJMvFy0f zdSXeZklFSyZYW~F*!02H_}S;JjjwLGt zsPe9s^jL_ESlgU)yS;GAvxFIHOBmgDA8QQUAlCxEkbNtAZv^|oc9^RXSj)R`XIso* z14qogG=S2>CiEps$W3RG?>>v(``73=w_&!UM4X*od zm2d;9&El%i(2%3Hi8rhbzjr@d*?YEUtr*zY!i{<%AXbbSuYgGn{We^K-;O7qjb5)l z4jM3(vEgrenJw-wTyokwW3bvV!g*gFC9vtZaVTc;SLP~Q_g99#m@9sxbo|AAl5@hs zVB`7z)MH;D*f{J2!b-?lI0D#ZT^=9rzL{eIqo7iKpiYspKAO$hI+i=70C|D9SK z^KsOJXJ(5%+aa-8o7j$Rm#%DSM|QUNPJKGPs8}3xuyuS=-jVKG=mpyo(-lfB`94<} zv!2uafj@4C+p>%Z1PA5=V=_{^pUmL}=8na44Tdf(K-tGR;&HiUF(I)(j`iw3W3UNW z=C?#d2;+GX49$XpNd-&w#$GzP?FPKw-a|Xejokq@irf`=eI!w7UmX$OAHo>?(LL!= zmM4&BsqvsH#M$-|d`vKV#n_y~UdwPV)}N$9z#iYwQU|clZPw|TEwPy}TKFw&@{Zw&7{&XlglU?Q-5412bYp*j zs}I>0F6dEXXTBUq{2K`>_Q8*HQ?fE5co-$5YZ+xk_w z?30Bj!@G?**mT-GQ@`JP4&O^6n9jabNb>#x7y_&=xV!Ee`b9L{b`;;M?<)@WaaPyT zul{`Q(w&S81Kyp>d%Bih1Ou2U7&w~Vju-ANyOv%A0}zHfF7KVe;J(6?p;y9~dT4;- z34VLqVdQMgcf0!cTCFBq|CN8VVU zkMT$~kk_hs=2pp)Sf`Ns1eSk1*fm#kn;b7*V7LNYVuU2zOY^L)lHI$nIbe9dh9&Or zf8~$sMstj>r0EOc9-t}%Ad&&-rdxvJiFjyi0?%e*kuyMnlf~rS{P7a%RnO)%mH;(O z2jWRCy6FXL>qgoejw?nKxgZglNWsm^ImBVCU1hLjm3|>jo8?#iO?JCo8wU3 zyl35pjU&az>adqq5Sw7pmQHWQK3s*Tm-vXVhkdAU;CM9{?7$)hEGtIgycs8BDcy~o z-G!^$aL%ui8eAc*!zqCZdNzu5piuLR{~Z!?~KMo-|9+K$YY~g z_#+ND>B@2-m7g2&sIazf7|zrgEODvdQ3Mt7SPxOTR|{QeWFPOn<5xyJLO8QWKXV0< zyfA-qFUH_u6b1&+>W#H5hGr6WS0Uc@6pc}!HL zMZ+HJ?7Plxyt78*V_%vv;F(!!gVmps8}Eov9uw6_SF^_iWE1mKTN}$`X_ApEk#LS& z9>tA!glyi(4MT_s&)#lej|_KIG+tozka*0=nmH0~8RQ=2*JIkThKd^+s!$r^huwl$f_x3NcQ-N=U>vWyMn+p%H@b(WUTP>JX?Pog znDhjA&K!IcPyl(@M-g7HkR6jGvA(Sou{4D7uz~!YSOkbaTwAGx_qxbN9zw3)+3X%v zAvAu0JE${rz#v9%-zUBT%?Q4X6tu;MY1G=-21!Ta+}W$(_T1cG`2U@g7+;g=l=?n; zI)NA7ADIo-PKC2a6q?2;9-=Os|0>(RG<)AEe=zEl>X9_cId===X=gU57@GzmI)kXd zadmNRk#wxWU1Y?bH(T?h?7`Y1=dd}JlS+%6V@?pDpl?!ViUs#@1IJuyMO~gn?=iTJcul3%F`x_4EW&IN(3qq3 z!zvAT4g!TEUZuMWItoX;rqj3JvXCbWVRU7nTs%K)lX%S2WcxkZ!DwYrYs^rEC^OpCovg!JFJF@mPGchPdi1v zA`);cNCHv&-W_C*b-jZUPHf#`gh?~=0C-f&qLOIDPwYtI=EdBU(cF|p9K}^`beaxw zg7(;=o3V&2I+AI%c5>loQrj0VW3jTBU6KdG6~I1K0=!MV9Zpe58;c$G|W^XoK+|3Ekny*q9(Fw z$WFWj!iq=_ale8=C2HavuFx>z2W9T*OsxJXo=B&$I@!<8CgRALzPc_#N;6hQnwSU7 zBCODGorF!P;bif3u=5=+4WH+_2rG(w3!zeDYa#hXqfHQ%p&a|&5E)jG>*`T_pg9J>K816Rbr@d1Y`o2QcDvR@)czl>Z2R?{_kN;t81u@jQ6 ztl50@$|i*U zSY`LK8j12Qn`!U8EFW{~n!UmrkyJ0zGfeMrN+i`Q1d+S~0+CZ2_#(RKrHHo{{35v} z1R|?mv5#In>{F!GD}a%`3IZE%t)k6?K1Eus@&E~4imaNM%6o@=uh#fbJLMaZMYweL zcuOSKD`XRzQ$3~Zh{1cj^DU8B3%EyDUfIBD6>aX}mdLAD#3s4*3nFq_gzFw3OUTyd z)hlGvZ2f{;Fsk4ljo1pax5o6vtzQs!PY7$kR)kF};xn6DE+zsegBN*+TQ+VIXpvJa zCgP@5xO!(>B5GP|AEGT4YhKJG(IS1iC4wdc7kPyuB5G2y3qqbeGcORI0E^iW=n*c5 zV~tKuZ6y(PF%Kf~{(hF=o&yTB2eQOWVc0r@)8vTFR;mD zztI3O%oySfVg;CzS6U_l%oXOTUV)f!4N6uXY>5C=*rkTw&gA=Y(N+cY@Gdesa|91CdY^oX0b7+U zayPCj1RuW4WbMl)#6h4%;M(6?ipuj4YmWTlbLmXX^>HFE zjQjz~K3*m7mpe8l4|lX?DW2@puLj(R8${;gOl8~b_ivErMZy-Wn9aS(=0kN|^q>F( z__&7(0tyg-k5gP{ZGi-Q>{e6>BQq`K=AVB+{e{nuQTmP?J8r74g>!7)`gJSp;ATZIb7=BK}ff z(^8}t+}2Ye?3_yoqbm?2U8QH^FC{8ZG;H*x&>~r(XYH*LRp%KhEf+~a+F+IvUW9fL zV`ri^2~NoZXc4t3fazlmbDqtM+Jvw^x)nj20*Pc5vvLhmSRUPqm`#90P6f2}3`$lW z+}gZcphVbb$UKlM@&>)|$)y;-AVhgxCoNYdM+a7$T3 zc;?W!tvepmZ&9@!L6C*{+;791J7Vf4vsJ)-%4a zGeE>98N@)1QxJ}%ZrnWF2Ru6{(@o?RK$KxzIb!UIgR75jBCnt+raq(y=MaPu{ia%h z5Jm1uRuN%Q)_QFo)^XU& z;TgRmvZJ^Eg!IVbTx)KzVB4Ota-G1?O^7$|)JJtQueo8eCpXDU{|!b|y!ubEqgUb5 z?14h`Xh~L_Cv>m;Q|xF164?_4H_%fFh*SS5V!c&*bni^TMqMkwbmMW6h5BMc8-OWQ z@6cDpUJFRnvRkRIw)7&Mt3CO3V=oIa={igidaV!>n`Sh`FG4Sc5-oL@UbE~fTD`*o z8+j>=NLFB~<{~R94+d1+rLqAH?td`5i}7gFt?d_PcLj&M;(TFr7tu7kJ@>7}3%vw3 zv=->QK&_IM=e{EHQqYjB?YFu3DjL00UmJEQU`Um#3KOkF<;jZ(x)d^`idB_?7P9NP zOLb|ZL^c592k!_kjt~`3U#m~0w#sHY*vv|t{a9{HFBez%kgU!Zah@n%lIOkFDM)Zg zmgWneAnKm-htL4@KD41lNgpxU$F2?M1S(2#6c3iRj^B^L6)+SzYS{m~6lMm) z)3It8PGal1zChtZnPvcM6=`tndo7)th%4#78&YPo2t6JQswxq;$Pi@VIuRaV_tf@a zK2mA8kgc?uywq(V9|<%0O-L3PLjHs(5Gy0#=NP2&qzlPPXUse%6fccIE1!z^Y$C3( zAp#2QtH&mY>2Xe}@^B@L)eu-C)(anT_WXoQ&;Uz_RQ9uRtm+xlXLMJQ39iCv5`u|L z_z;`LatE{(1Rx+Lm>p~z%w5H5Xb*vF zapSk6EnvZ_16Uj|16VOMW`ifdSU5MJXRWdIxkcaxSfPnLBa&|70rlv!7i9w1Y^`{O zwz8f`2(PCv-ljA-QFIGH#jaeX+wcH>u`3nUvlM_1XHP28$5 z&Ia7zP2>^|x-V>k!I+v?-!E)}5iZ`buQCY=BT@za(k3Y3<>1$g!X!wfn*(fGE`{a6 zuZ_bLN+hd5MHHrF^{Il0!Yl`+E&-JtO{=IrQ4rQg(PpeQpl%2E2~d@g-Z}HQG;>i zAr00#On;4DUM@u8%@J&1Jz-FJZtA7wf>szykv1RS%!_{?CoG!o)(S_Y6v(u=#9+^& z+u1LWq6E_#vB!Ae0*l!Eq}<3NF&?nX*ta~B!eBpRyS3R17cFK2%O$XDd_G~jHNptS z$K3Ja$a?FPvX_$!USdq~2yDE}7_!JBVxR8T3K#A*1`35#3bD8;xdM!kOEuyryxo01 z$i-AfE_j$QRjje>tVX~?w&tbe0x(Lj{@AA@PU7m1dpmePaCDK8lHjZeB(%dgT&Q ztq_=NHl`h^WS{fa07g_nCW6VD{@~-bLKNX1tYR*(xk&PQ^PPiAQF(tj4;~q__58Uc z@Ewkzd5!VavOeZFfV4}Atl((xeCMb@y2VMB-cz97wdTWp( zNH^xfuyW+htGL|p6M04c zBKT6W>IhhbUIHf4<)b3-QnK=BLAEg&m`K--sx~GgD$gXW&660>S~}`hQ3_dkB%zF+ zNC*&yVD|XuMuTKSE@3F0wg3@wt=Q1;O8Z5`waQla^jAb&3LKKP{hHC)3d_S^;Tse> zwDbjJFDF;B`smlX289pl;$Gnzl(0T+60SjEL;*$?Q&J{Z8dN-CbT+~W)CgvGMA^LV zr?@SyDj9$<_X<)WhPR*Y8B%$8%}dG^SR@Pl zC7-h;{B}-#ZBj1KqPXowG_u+*)jmA0U_~)Uq(j6$Dw#E^u{_~(HfT}WzYvoPH-|lu zLwZ8!Y>JsM!-LBYyOB+WCHoys7BK1?4J>>h5k0(h_kv=<*nvo%wM=7j(rcW}r*pP& zQQdYNk<4?*1|B7alF-=-Cs>uj<4@Yw`vIiG=xoy-L@b4IDSJ0*j;o+_wjdK?kV$kG zlgae04L2nhC=(_ai-mU$4D1(L05>OB(wNG?Lu$gzops+&Xq^pKgr!OJ29F+j9aK)~ z39Yl0#v+6lO{8$+p8V8nr&^l~ScHIrRalfm;5N$eFSItYc_UdWwpraNABUHcE0_s> z7VnE-0ugO{oL%bMtgSFcfpbqb$ih1V@)KTXgBBsrL&gY$#CC!)pRhWwqS!e56(xH@ z5qK$u>m*cqjCIptFcT60tl~!}gK`o=8b2GP+lyTHq`~h`c%2Pqgh}BIcr1^{H|G3| z*x3jdJU0R%zA>wdyU*)v0V6D=xkrpp%NmOMgxJ|i^Y^%t@Ee$mIiFp`Z6PD%#>hih zUP|ZH19aVHM(6k?qG^{RRwKnuP3_5C=wf>~C71a621mEabvdC#EoYc3Ih^ ztmbZpc^<-QfJfbizKVMVd|>7pnH?kH4 zQK4J3Ds0BV!-t$h3}rY3%JZ>s)j#uDMEB5iIm1Xko3jOoWZ|l0bGEYj3`6W7gAf(3 zxL@obBb@DFZ*)u6B}62PIK>8%!V;U8K%{_(mLg7%P(;eEz`hf1DTGLuaN1}~$ZAku zZ9%4V`Fx1^%?_|u~ER#QrjQ=I?9#ldw8e5BGgjI&{E^?23ksXJ@xg%ECmhe z_5hKMD`9!)t2&tsHl#~VWh>JvYfdgaQ>nlqr{+{xODV0-E+h-Ig_ekCU@WoQ$Ou%k zPXcXa3szC#FAN?fw&pgjD~L&!`HL7!$?5}Nk&G*pNLTqw7U++{#XIk{xwt@ymKy&W zs?P##8s+qPuka26B{EgTZi}nvlv_`!YWG>7ElN~3CZ!esV^v+P$>o7wJLM3b;f46} zEKx%s?&jhOB7(Q6llMXFXy z3k@N^CBn;#AUlm#@_C@GFa{OFgx|sQV8aEssma1hX(Qgi(t1{@h3OYhS=qqLLa}D? zjFr_};|UG4g@ytrB(cPs6&sJ%7yYK51$)MNl+viJWx}i>l64 zd_rh}5n)oX{RpN_JbG^amElSlJBW4lhzmyDD|4SvLK~C_c_Kq`Z23+axmJBjXd_#A z$s#Wc%6RgYrrY$+>z^x6joCHXVl1}G*R{Jw+B@?RX5iq}73uO*VG9mU51DhcpzOg4 z{#369RaG@*(-!I+OIU-jfXedXe>xBvjNWE~$176~x{&z)^Hc{WU4{BJ3Uk zi=An3Bd<+B>|U-g!+;FDMOFIl1OJ@?Kjut?Jdeq<{DT{5bb(LGVIYQ|C}*45zo}BB2Y9jDHO81mOo*VO5}1?ICm@NT4Kb5b>Mx0*4Pa#sf4k2N zZGj_M?XQ`kt*|=$72ZMNM!HYHhHXk#AN?v~XbU;PHsPi4N*t^9q|{aj(+TV~Ts*gp zkIq$hbLmOEn zbo*WL9O%IcC7&PK7AKi%|LQYD3u%4uYx8sgBk>AaM%NLO*dBak!aG<|OcXsb+kJ`e zl~SINL>mwZ!&)Z&f8?0rxu20lTj|bwYH2C4&BEsfR-2?77>UN5I73J3-_ql*7?q-1 z(aK9|@ounijn!Q32}QKUkm|3i+%to%?=W4QsV6+q zrY;GuMecsK(DLqqQS%d`Xe(VeI0poGa8W#F9PLS)lf{lO0-YC~%>72-+@G~Mt*{k- zH1J}0KCJW3w|CQfg&kqrWmYy~2Q*f%d7On(IPzj%SUBj$ScKwpMH}cSF@0o00T(kc zaOnwG^eQ}gr!Prb5sttnH#dWj&=Jy1)?3U@JHtyoT|XhD2d{2~F9;;#BX;is8VUp| zyj-_;VvK=>cl`-hw3UYQfJ?4CHNbFJ_r`jK0cBpVJBUrv$j;=qMkwj9@y;RmWH$eY z2WNn?*a`%SyFElOfNj|yCykmc+Ef=IPbF}~C66sshiG@S=uhNzuNXKImiFm_5ayDn z(QM&u@Tl>Pw0AC}FK`#>nm$_*8~M=a^)a3i2B=_9-hrQ`Pa#hi6F4|b)A~4C>}Uo4 z=&Dk+rB`Y1yg_Vfh5qQ0QppucXuBx_1V;HPBQ;|4D|H`lLqul`>$MSm3D z^FDnnY_oHT9O?3Zv7H6ul0F!gJkbI;l9ip3DcUkF8R*|VBT>kauI#iSm>}lRrv{2E z+TcdIs8ex8TiRHCWT45S&C#@j`F|vf76wfB4Tu0tF)iuhe-VF4VSPR<>7p%Yq^kcl zU9^?e$HTJe$pB8ealpo2R#cx1TRW}LCRqck%(N8Nr!tZ<+QLSii8uB?x8i7_`;^fu z2kbs790eveTpsR;jzpa5#>Pzc{$b0^I{l6((Jn!wOl+TZKV@%n^=YF&qDQLwzx%w= zMpz#UE8=KV?&MVeOX6rNtPh1nz$faRoZ5fkA(XH_6_(V|7C)-IP!)C%X%JhAM)A3$ zt#ID3gJCZ5h=_es^iRzcew2BABRxCYwedzS6NwUz+wFo51Y<42t5=^t+TcfN+wqM- zhmNPt!>5p5WwHJ%3kG1fN{FeaCmhly9qC(Rd1>RF69`ym7ZlPKa&o!_gpUxw5gZ*M zG9+$9>S}k}Vuftki0C8gV?qAx@d<^rX{UoQ_S+t_@>Dj4_=G~*Vor&7MK_f(+K#RL>`lrb!UU9seOL@1G-ut!_zz`K1J1aZ%$Scm-fs5gbwuHDC6Ph|gmB~KzF0+^Lb(wdB!xsApD9I%}76Y6LK z7d52Hdq#nf6T=YO6YgkB(ak$@-!nzJID&z1YIcibh4nGw**z4Ir{-|$W6)069dg4ZBD}-%wIA{TM{RyGeA;ETNbxjXxODEksy*T&lR>_O3ULN$s}zNsI(E!;O;LS%Qt72O4`U`@kU<5#rjqP zL+*Xc3V=ei#{Z&iMB+bOauOlid95QRqp^DM(V*mzNt*;N=w;+MUMrK z-+n<%|fw zVkq?qqqMmfn-@EpdmuEUv`K0(A9QeyegFnNKOvO1{2aX4@qG`cON}bvBWx{v|4w#? zm}?aGUKuM33&D#HD_Nv!e_T>3QgneG&5hAK{Q?bY?oY_1jVv;ge8;Uyicg57E!+5(Kkz7& zXH3%ez9Zi5Xl}2NOwzX2X)7Q6S#Lv*O0ieJPVuQX&=)nTX^5@ySoDXGADuDAj1^5bg0Z;u_$dpBx#z=*^nr0^<%4T z@wuE=S!9;!gIme2g%;3F;Ejpz2iv`IRNhvGFZ{sa;NLATqyul1eZPyRPseOoeYWMT z-ScvTge14b)9xlkv*W=0iWgbnAWMN~b0aM!EOCAnYKa6uBlWV2D0mh0YBRX>K>9RQ z?Fb8)=n{OfAp|>+bC{}_m@U@g6iP}eW>c%PV&&28K~t635#VV`vkzT{)JD9c(#@AENRS$&i$+lLIyvKG;Izk6tvmFK9!J1B@{Ex`BU zB_*p5QWY7qL0CGBEQ<>9*zjpjn3#=Zffav$@1{?&DFBuV8;ivo$nhVru-ro*$)(CG z5kIq;wI@W(_ST)Ph`WL`53@b`MR5KBQgV?_0kr4}dP&4=Wc4AcbqfNbS*z#Wt|1|7 zj!-?9AV8MJTUjxgL@nsUyHCVydAhguk@eB<84@T9VhM3mpUP-eT@Y_%eGkO-Cq&GK z>;m@n{dr>a$&?LLf_45eV-jhpHOt)NaJ*On8PQ4%^9iG|K`Y2*@cstb_Jq*bG7D|_ z!2k$KcdMx+v#GsDcEQt{+vO<&2whJlthFjo zUJ*4fmUdY|oB~*3J3U$ubN10(Kv2+vI7P6sKEU>d=<^TBu4;)voFXSluWE8ejg$!! zDzZLZmK3(9Xs8x-qMA$U5s%l}axyD#!QT{vrlYauF+KNPj^~}0FieFAIicgDb*+;hWvEa;SMYYHH5)yTTW0CWPt$y4}U2ugO8>wqR zg{@PU1ua#aZt=P}oi@h^-RBCmr_(SRAL6a*lc6p4J=*i>>~od4&)*P|bKkdA7!O=7_ipDlW_LuL~_?eV9SCmr{u^U2+ENiwqR!QZrat#|z4v zYei?kdgS2t>Pl%R996su)}gH6)@c3(w5wxS5vnq}e}EV~99fY6A0R;)1 z%ez{wtcl*d-KGwaSKM6O<|z`@6^czFI}ZB?|Dx_Mhu_7bp{6NoOBxn*#h=K0!HZb; zRRK3RB8lSghUE3@PM=)EW5Q5n-YY;F&~_7MMQrDpP0ldp!J)B%W-I`ngb!|z+g%7! zvl2!)`aY_=8F$#f+xDjq;AwpO+??Xj6ByH;D({f#@) z{yC|(kq7uDjD(nH`7qIyF=N%mLzrW_Z}{)Vv+R1CW2IUN2UhSTUh+w_@`mNtz0?H( z3DSUo^hcexv|TYF=@Gex!@U9+!A;-OJ~otdqiHlAvV(X8bu@DDR8R3LJoksj17i(w z=hZv$j#4a)Kx7M1-urkE#otcumD*L5iwnLFiv=k-8-Z@#n>cOVTR<>vy#HIDzRM{h z_>9D5lF$P2W^2xgDVEj;tfD%KrEDNQ0LG({x#oVIx>Rh>wA!9hU=xST!-V0zun@&Q zgb&OWSsj)*0xSQ8g|US+dr=}!PY{o+y=71w-xKeRyN3mWdvFUHd~r$8UEC$OJHc5r zIEw{$XK{CTcMTQ-1eYLz%kTNu^X9(3@8(R^RGq2mIj8%3y8E-O%LO%MSZ~g9OC$b- zN}16T1=>4WA(`JfQ3#7RaSPW)*D}3Z0f)eAw+i(4d=g5&@>P_IeDi2WnrV$!gXa5KGDbfpxjZbrf z5ya6QF{c=i`mL7@eH!P$iorS)Lx2a{s`ygnr%tHNB%^}Y>F&Hc;wgP^Z6^2;7; zSL@!Na1pdUpuz!FDkV0b5~3gzGtw_-*oKN#fWf}CW>%udv(b_gkPIA}du=X^>nnT5 zyDg21HQ4YSeDszS*k?o0Fo1G*@sl*Wt}6mN4GUVCJ8U7rpQbRJ8%PjptiP;l9FK1@ z&r;WwtYske4moma7@dXpmlkaITwi92dpS}O!k#81)ySUPu!piV~c)2 z!Cu0*fiR_@pfKT`Nwu7?fZWBkNs#j5mrVqEES2Rd-g5nV==`+>T%@;PvPD{r+io6M zNoshbt`p4|) zT7{%@YiNyiyzk&8%#a21&x43@wgfBYCKRyi_RAlQ$E}1i=aeW%chz+uP(U+`q|-*CxnDg zZbSnXlm>qc_#V<*l;QBYxa0bxXkHcAROBRvF4HXzgKA077g~#k&WKk6MQT&R{6kWA z`Yiw8az)&H%)oN8ah@uT+XoBg3f7IcD!36m*3yL{wd1d-#;~Po?@S*b=`(bi8!`dH z{}MbB>T1m%TU-IFOmq9`>XSKV|1gx^mV5CwSIqvLLO)L*L-ioAM6Sac-o;`N+S%zY!9; z8$B}C*LnSCauK)V>}x|Br82J=iPwmt2FpT+a6?TcxjPWnx1KO!Nn$9_8p|K$q}GA8 zBLoZ{)HhM|_)2y497N+$-^!aA5%LxfBeX#xR!SXLSmNl5YAkJQWDj;DCy9=ltg&Bc zMl}F)J6s=2?=2@sW7{^T>AA=Qawj2^v4{0M;jSLk@y2KN0sVLLaKfCc&B#{n%j!5^lI<@N- zHYruqGE=M{ODO6EWDNS* z6TH{(0mW9bRjalax2_@%B^yGGl%gweN>5WBkgK@zVNy~{<9ZPdTvYOU-xOnZvdj~N(BQ+1YA zTKn1-mxM5XmtNJ>7pO^oX!0?!jdCw)bytSa@E}yNbl%d|8d|AXMAs*6N%~z2{{rbe z9T{*F`nlD;!A+gtyxGq5U_WhYw52>l6;g$%nj$i2`-k>K`gXNtrV@intB_4VrLl$I zU6gD()|7!IkEckBoc1`$IZu0(Lw?oCNSi{^RLzV%sU3E?mUomg#H7P^a}RRt^|MGH z`;f+ASCjPx>BPNlP&)YDx{f)<#P9o4qgu5oG_Kx1J`Yz^I*#4P2f}vB9ugSrEE@{( z(gQ3hm#8de9{DneMuo|n`T(ypCcgd>G%5vz_Oap}b=CyJ?<;i8ls}FUdNDPWOB-hG zV^$GJ#OD^wu&O@{@FN+Tg&@H;y&FSyAylE0{Fi7&w5j0*!}H*#Tv}LGFFXFneC=U2 z$aF_f%e~xi?i`DY_i0xj!}raUh-Pz@Dq4e+Q|b{Ua{QO=A6ChR31d=sQmjh1Dan0! zc&9L8B%By6j%7LEzuMC>fz1PUn(@YCg$1SayoNfMV(n4dOj?mDn?vc+9f%nmzQAfF zlu@9w12@*i(#Zmi^A!ew-B0L|oaA&9swXCiqQ~EZ2S}1cxD(VY_CS!)A0`azKcTD1 z>hG-%ccx&9d$sTAVnn`q?@?A|n=Y4X7eglS2DvDyVb!S@(6I6<{15xJ|SO$-C z^=NVwYvLD+!OY+fo7(f0jF=Jc5Doo^RO$(3onpw}^XDc-U!aJ}Ptry@+KF0j4%5?b zY~+FKF2D))o3Qg!4Y$Q|a>_3wcog!TiX`pTuq?l;#3lWt3Y~)s?ZpId;z~+X?zRl5 zQ|O>F)J;ER`CRmv(w=!|2<(gWIo)2&g^mI#0oI*4ve_y1mf?t2f`{ z9gqqeJ%Is@ZQvgBW&`AGoTnTLookP9sIC@*ZP0DdSCdjjw+!qcf1N6LJ!)l2o@e{r<-mXukIixXYpWWzc{ooYAdE6hI*Wlu}QzhhR3Z_Ed|D%F%aL5q6II|=~P zZ5WGD9ooTT!1_M-WIuonC?+hl0HOF&2zp{K@BX8mmr|zAB?42uEt!M(n{{gptim zro2DExbJtiXIP(m!=lebpq zb-t3i3$zcxQi1br+rR4MOMYtWgp!OJGa7Y-9LROg_b#(5= zo=GCUKxB;MW$1_@wf%PZbr(aXhwhRRzGb~9?$PdMzpeE%LRQEQt656Nyg zE&ll{xRUNMVhe9vSlAnf*9okeJaBJ?sWa^x;J#r_5hFN~cFO{f%acFi2}G(`1qVNO7nI53 zZ3D4d!NYDI$QoC2x4B&?7s=*EUvm6vc-3;J{2Sz{7lZAOc!>DJt=maKbH3@P!9pi( zmd+J%WL^Aj8n{SD5{~qQFoXCfZ@ZZR)G`P`zEa}|lt0(P(rL?RB-)|D1g?wrp3F9c zj+S7LdFA5R0?wX8fK>$8BW1OXEZoB$-Rc@;fL0OZ>O5RR-75N}>lI;C6w@}Zuj~nm z$QW>rK*P2XFTn}QPVSUCKPj6ir1CzGrNh`-1bFIkW764k2mYa(8x|clOLZyg^PZ)i zt9VGi=*jvS!#?wgl}u_xU7cbr5T0=V&B5WvwYG#BrjIC1XjrGrjm@zv(x%7V@Lkx8 z)+N9Cr`OD|vWUPqYAfTHQ4l_Oz3fiaD*oy(Zc$pK$F#1T9FrN&i@n||Vg^;TOS~VL zb(bmbz>zVy&)h0IuXj~j( z3)@JV=s4CLJ%4}4e_BXn>2>^3#A*;_sq+VSI+i*IYNPE?$=1zqRM%m{{-YC=)Ic$_ z|Ec;Qsip6=@{UhxTL$C@ovEzzg}mxiu}En(f`DZN2C(j#1~4>le2yg#43CI;liCPQ z$T!=8iRhdg-s{SD<(Qqx)MGzwo)RIR7R}r2%KQA}bo=MRu9q z5{j_rMy0!E;)q)2S*m&Mget`#V-;sxyy6iw9|H+sBjZpVRT>JWVGh#B(>yq=3sfux z5pywhfF`SUjC#80kl=@>{eyWnTLF=xMBH($#zWrOs`({g@)BHF6TS+2r~}lD-0BR;MoPi2wmHriu*m z$zVT|L5`#Xa3o6wOG9~w{?8O(1s+ruWCfDDW_9}=Q)_jneQJ{(tLq-K8|ZGn|J^UL z#|B5P!v3}gI7GW1&1ZbDgCAW0qCdb+Nm%hSS7TqQx~~Q%pGDjhq3zc4hgE16?L)AR z(4z}!k80vHY$`yb#eeqPmEL}l#C|O5f}S33aAZcx^3U6G?P2%_j2bxEZ&_h_X4R#{ z^j^$m5;C7SV=Cq%yM#T{T8gkqY}m&q!JbV+1%J?y~oZg&2?AMy{5m&LNyJOcKY~N z)N)8Hx|UG3>-lA^=&YJUW<8#cb&ZEr?BW%#y<)BS+8TE|o$6`{ZfkKjxg?`2+6pth zm_>E+an}Pq3!^iiRw9K5y%DHMQvxh2r&G012A1JLd&*|YRU;ZBMt!y1t2Tpw;M81b z<8k!3tcM}=%BELtW6);p8et8Sa0wq3WBI+s84OK7imjM#xTcx5;6A%5UgnShN zKI-oyRHXYu1jIgTRV5C7`qJ^0s5>Z^zeN<0;9IY{ESC1=bp*4+)~VuZ%b(^DnZt(_ z*|?^gI7scmsC`v=unl|cXW?1IFxLxVvTjci8)14YR?40RT|pU5U~`A40&Nqp2EjxV z8#+_LL8xw3HN$f8qcOBxSQlCbrje^Z`qlYIjf%Mf?EgcOim9`#nD~cYyjW-0xUb4iHEh!luHvAoJ~~)o5b7E)YHo#3_bWGzxg^0(P$8h z*S~Rr^lVR2_7E9HE4cM{B;M!0$Z;UvL+*G3E?zNyWX@IgS2iHe!3YK&CD#<@xx;f6@)z((<`sZ6=l zEidcO!6D1kv~^k@jJHZG27U;yu~C}PHcOKfLItP)I%*d`K(Ss}_K$M)VWl{3K+X2>;CeqSc- zwYllB{%E+8!K8afvs?N^F4U8j;(p!z&F1$H%UCxh9_gnYqH}IY*q+KUIpjw}vW%xk zLDRExQjb#^9R$SBH1#4HerJojS4x?fRe(buWDe6+(uY{NQ|sk{F9a$VRi$h}i3D{3 zT^WU77D$~UG#9}R@&y@rgomjD6v@&8wgN%%;txD~hYE$I3m4x^R1SWHnOEu0R9i72 zCL5dw01*m%$I`6J8f(akLHGF5H+@|FArhHd^N1l{hb*Y~`_?CL-Ads1QZHg|?;e+{ z8w@76x(+_Zp-_WBZF-;c3Ujjj=9YKguD)x!+KQj4FBXB1Db>PPC8hd-S&GjVwNOP5FQkSQouB|Gjj6AFzsPBOU?kb3C4v z3d)nT)mauL0R&}kg1}LE&%$<8RZJx`vxk5V?X5SZGT`(+LOa~VBS$!^xkMYCF5{;? zL1p4l*jTG~20KDv<6D=l!PAnYu>N^lnUf(paegQ6nWTXwd;Zax+*%#)k~3YnIf&>z zuM(UDe1l>=VG5B!8JH_D)Cy`7B*w<*=i>vwqsG@Q(jpA5lul!^cy&QU#8%N~^mV=`MyC+n)!KzjvceLJ4qYm4>VMp_%5Z z5}-8SU9O96w%NOUrH)OSGSjYP?C?NIZ&`k3$ltfx*amFev5SY5%~hHcSDbX!1tWr2 z8oZ+*u%@=ez6}HfQV~!_Q3G!Wun`U!_5oj8`Kt2*qm)#1P%(x19q@%q$i`DveA2kf z6ahQzBR!9OEvgXo)bP~aBH`53|Kf^b_kQckq>%$Ye5ExbG|Ac_WN|>)1vxKFmrrNM=~e;a)5h`o3M*f)W!>k6Z^-O2e&5 zQ{nT09*@Nw*(dOys^WeQSqS%eB)~3k5>8L%FYiUzkF>fEmDGq{N=sTG0F z_8zW}5kH}mXgO!YuTd4N`_G%KO$3egvR;Cvxr{W;-reQR1U`!v_@qRdQ6TgnmKK7j zLHqwkKA<~J%xX8k?p6+9elQMlYZ+}ISIzZ^FnMUV%gIxb(>hvqU4Yjav_)*NGY~GG zVQ(D&9Zk47+8*G6brpdO)=nDAB`RWKpoIr#iK{1=@b5co1EWeU!BCy0l_B@_3h6Z3 zHUJ}VgmRQ)Rsf5S$FmvE5WQX^H?b0h+;mPs>+Ioj=hA@i9j}kY*fd%MM!7$UF!&NZ*HvBxc=`gK0ofv zkv?i10q#0p;+e{R8eSo2a$-pw3|Sw{*ii9U4SZ7$5^+GGKFDU$C-^Ku`_Pg%mbi0m~4O3AI@pFt~tvUVNPx zUjp&_&LF8j7_b=Uw{BQW1~^Q7VLr*G(>QkiYOn4Cv6GH4G|@F%;fxt6`YUo2%nR%<%|P!=6OR85b;pbZ zy;W+eLv3bF^RcTerJB70k<|If+N?h&6oc#YFa;%o$}(^a(3ET|G+8C6>kCpUzQ3P2 z>YuMP#~0yB&Vc@z(Vn_Rr+CCb@0sNe+OH~w5FZ|Va65{&%hWS9vH9}u-M1Ppm!lc> z>_BJ?IlK`RW~V^>HxzeMepr-b6LV|F+43&>8ks&&H2uDui6hSIJRmUxnY8x?+RFEh zLut7`9<(=Qkk`g!%YNxj3g(Ss<&DmMrvqiU!BE5giP6|Z09-bI^Eup*9oq{)lGIq> z%gr=u^)>4`Pq~I36+)jF$?dx`l=Z3VJ{9BF-?((o%nQY99jl-|YqKgeG8={2Jy@6U zA4V7@+t83UsA*{GCo{P28wtr;@ayrb!z9TMD1<3|l1 zlm*|32Jjl#PpY(fSU1|9;xH1>d`rl>Vp%nUF{)PS#mei(%FDVTOJt5dn6D`fYz9_I z+nWoe%&_jzVsBs!5;QPh;L7L!#BPwn7HPk}7b_V)%qh znj1pdmUu&K(mqL3?R}vvT3{Jq>;caW_RvnCB9$*-=m_%iXw)%h-{-{~vk-Yhv7@b}s2&{?PBkv;Gb7fnTzM>6L=(=4LQE zF{%;-TW2cFq3Njw_CeXmrjCnh73M|h#6HN{Asf^Qtx@QX)7C_CRd|C#va|&1o7UD! zE|@ETnRm^qD<9-INWyrxPFPG%BR+YScJ{k{*Zw!=9kSGebU_|$kHAdZF)^u88Or^4 zWHy0oa6QmF3R^#9(!2c%f1TM(s#Ukjd~+p2zL4?K0lqm=?=sxV+~8vY=I_M;Uzs6- z-)bvubCrV9-xH`}E#X(>%?(@&$aF0BAYjNXTdB`Y*=$T@?S)}dV4p24*Mxn?O3){0 znXFBtvJk%s?|VOqn~NV`v(uI-zn7gL5lO+2CPx76M$+?9u?NygM%nQnMvv^NR=_Dn zV^H^+C~4hf-PdFlra3JZg0oZgbdlO-gm?Hk>V=qJ5&*khovm*L-hOJTjY^3QG=!0Y z?QFjh&=YoQuaOaEdM1eHo?u*`rYVnIGj0GW5*NT1n|-%}vuCVn>pAw8KyLKH{oPi+ zimL2mEfUEsy!+xYCFzTGW*_9Aha9RUYl?*DQNAp^9IOjb*{B9K7PnD~;egbvSa8Dr zI4x_1CRAQt_05-1@CTxW{c`N+Y;Z4`*`8DHBjgDh^k>i^N-5TZb{^i_Z@+_m*{=(y z``*gvXo}1a$NEWUVUR)QgKm3?_Wu2fG6{_=ZGxDU-CK(r1PFQt z6xQS@bvy$dh6NTK^j?fkmS&@|@(xL&d;))v#T){lhv<99DpcBrPH^CKKEZyZ^pp3t zvE)ea37(JgorEk55sZC_kbC=@L;KTB4v_ zL?6}B&8rIE_vzjrY8Br>JV)v5qU_Eki2nO)wPzwe-iK+X#Xe=pDQ!CZ(sf#8;>Bb2 z%EmQxjjX#m#@7UlU<`dps%(PTbp4Wq#YJ;svQ2sjv)zF+7|8P z9}Pd+L9R&XO1W3^Nd34O!E-glKNR=0#gZn{$TRE+TY5`O3O2b4ms{dsk%ZN(8Dqj_ zY7_>rR9iy#>2^09=jn^NwLOoli57@poW34>Xrrc{7M?oM$~kgN@<}9`1WQVjC0~qW z`iG*~TMxKr{djW(HhDBFt?X{R=h>woynhwz`_SkqD|jnx@T{-++#fT3*@}SQm5}LJ zU-CJ&P2Mn2R;15={v6Tp*Ci2@kNevH$OuBIY!@_SA^E5IgE_{&d za>Ak#Kv|_kK^n0Fs0;Rxchf|}bTUR36z#+yj%O;02gSpAU^vTqVSJN}rW2||z-8hx z6k!@j=I?U2lLipQ?^t27&U!(e9j(3kFi_Dt&ah;W+pU!g6=$pZK)*XmlXY#K!ig4h zv(ziE9vZ=8YHT*hSmwXLx_Vp^T8ikMK+QgP#VQFz7?Tceq|ld@Q+7AGDgySEP~IKo zRPVY^n-3rzzfCVM>9-o+>ZgyDp(f)Pz^|b`BRps3vg-AUCm-|JkenmLd=fNFn4E(VBRJ$gmhsWsB^gM0{AQ4akLx zKe*ZpIe3=KfMc%}PxfZGfwS%a{mI8orB?n7KR$`Eq7JSE7^A1bVNO;fA*BpRL%A5k zO0^dCa;m7LT}JD%S=Dp>y=YHb!>y$Nb2vt9upo{C5pmLJ>OsphRLmJBbyXuWMZfnq);gHZLr+t8M5{kyxTR`aO z0r23uu+>&hC-10j_?Zg(@to!E-ms5WVO*hp&$@!`5IFd~0TQ?FO=UMCHvX8{d2bJ! z6+QEO?OkHbG4o3p_+{$+{_t)7lXVU}0oHQ|ywMw3t$6zAeFGBwafd4Pc(N%G18DOL zwaxhG-#^fw*!uOXj7S^Nh~AHsiT~6#vhYq(g0T(4w`HEc+yi>N}j}|dtzRq z_qKHg5T;y-{_?8k=x?(^o#j)@-vPUaSXF{bi2%s93YulHrh`t_FmUSE&4%ESD5gAc zq+%wBpbE1P2$n$~RM$qRdeioW;+=n1_;6OXew{dcQ#+l*#cb$Q*Obb{<{vQ<24X~y zB1e#)^+yZ?0s&cM=lpU#2+avVxAZ3fJCf8T>|EmXo3zek6%}!xA01_gF*X@#fw<_M z{~~225;0c4d4Jij(sJXg2z1P7hlFx_2LbV~5LBEe|m=xR{ zEC5|B3mE#cV4y;|tKN=D&*JeBs7HBCumdR}elj`p&Cw+CRwhv}M3z^4&lrAo!=lRA z^AW4`dj}cghU3Cw=r1bBeI}dbU0ZUNAq~#kCujWFG&%*hqFsrBG(7)RM4%2^%`K$L zOa!Z@IC|*^ih2C5#p7a=#_Pfk{(UqlZb~C9BV>7kt#`^Wq001m#u!E&1!kaJ>rL1!U}%-`p1#dS`QQBN90mkL#N*b>8)p*tF9r!VSF>T!z0$s-PSRt1J$ zbB`36_h=i(P8L9%Q|wP$d`g&MDHv`#DyQ9I5~xk;qtomlL5iMz(&kRb`lrL(z(_Kq zwsxD4KS=AuR7p0+-46iaqx<-eTD7lEv)N5wf;T2E_Dp*5chQpVqGdX(WF zGG{zxT#CMi8y4RxTBg&iNrl$6#kbb*5bExCaI(T$zlCok@>AbPx;6!Jdo`9N6BI5z zP2nBcEKk1ifDrvdo@+gUXe4r=u(O#MPj(YQxJ@Bld-deGa?NNnwKsUh)9!M5%b)eCtMTmoD`B-<#5`8b{nUyiY$t+fCaIj{=X1S=@)UW3$o z8-PWDxS#x^E8mSQ;GuXiECXTGB4*5Drbm(mm!UTsfvE0g6yl>ocOcI=Pu}0Hzd0oP z9)j@e9t(e=z%juh?odQO`#4lcHa%XJ&KKzsU%*S9;3C0OcGj~T#aor+dxHBatS7`g zA2LRjdNe+!*5uC#vQ!};#XFU#zZs^VrVjvdAj;F@EkaEpn#*GsV4xV0`JgVglKEaI z<}S2hBPGOm&Yr4iflZLw_y}pQb;i!(lI>RNRm}xZQI4bCejgNU6x)_6FAq~s1)q>V z78F%@HenX26!j9+X&yr_Y|b|_j1o|kCe)e1ss4(tC7A7>D?+5%-A$T{)Kr(g{04kW zA0ZRF3TgXje|;2~eDlu=S*zAAIk5G~3GbXoFh(J0uL3>5}AW=?hTP zkbVxduM^b4q(g_rlpnPKpjnN1snhjTJw^Ju08IS9=bvqHWFXgC3Q|n~( z-d*TQ(Co7Olg;80#U3I#NgRLDpwsF1*1T@9G7UHHOMkWwCd+j9P_M6 zb$ds;3Y)4PMH-3;mMcZ>J2i#=WUS+)9?u8wUQw&__+^YKK=0A2Sgdq$Xgk}86iN#d zDHX1*9R_v3(A1A#Su0X5yM1V7%W2wm77BK=096vu1RXX$TunE+FZ|qpz8moTy4fh+p zTn;*-8*f*3zYJ=sE^W1D&YU;tNzQ>%!F}#NBZ5SKg7q_R^MLBh;-^V;aZoB%j{DugcCq8}s z|G`R~uk-3Jj43I;EHulHpXG~EE+(7*!x)MG-*BbpYtNq>Q&mk)N8VG2vSO5$)g@9^ zm!!vfD$8CED^)j7zOJmo@4SD`q9q9&H;(_DvcLKHi(bDq$>`2->|bm_w(fD9(V1UL zhtYxl(;ua+SBJhDk?MT3-I|VV@Z+hYSa#6H7eq|1L!P@2cTeqKye878{&1bFujlQw z(y4sc#yyvg<|<1E=9#~k5700nT?s8m#G)8tz@rMw*RBBq+VZQ)A@@OZk^f`kW z#0bc)fj>Ea^pJP$PNFmFV|dZKtPiMp?f8!qRPz#$k|@Rg#)%=je=YH<`i<@VMRXeJ zRlGXf`OmNv)yQ(Sqc-iqv(n#J_1)vw1njQ27ukFLssG_>^*Rq?E1Ych8TId&e@nK_ z#IjIz(HnQ@1Gn?w{;l#Flt;JCNc##vBe|xIRj9fyq;IJrY;uys^fS>#nCd-417>#j zkeeV4k7)Az!`jsWcI4|VfZ_j}RY3Y{oL-Ju;q3qDMbmrsUD#g#)@ooS>{&P^wjJbC z2Y=jrSX0wEuZc%rUtjOKZiN!bMyGSmYtl%<#UEw{o@jC`Y;Qk7v{ zby=dPUo!Y_!JpR?;-^>MyYA+^+m1gvwxl?B;(M?0BCau@jg}=}2JWXCVpEV?JmS8` zP=)@sCQY~DKmU+xC_l~i*D36KQ&+@}B$O@yIaj!b>7@CS8v8T&#`sBPaJcp!J4e5n zhFHqw0b$#?$hCqf?(|hJ?`cZNOR=}($T-aF1Kah`8dJs;@^#(oTaR-U;#XH1lf!O7 zxB#c895{gPIw@lh8kc>GnOa%w;Ly=Rt081*viVi$qte-Kfc--BzW~xFPR%{#8X?!f zzwj}_lO4Y@B4ztnPJveX^=7aAw8YLXq(k`6$Y%Cs!6{>{9^@~^GEPyBWAa#$vl!=7 z<@%Of7jR;u#REUaZ>Qa=4bDV6Mz zocty`ZYmNpU=n>i)-%C#I|ln>4jUmM@EwI~giMn~dG*^St_BFTO zgFwwgQnV>lX3PfdfA3ngL5YMJA(#a>#hRWA!aQ8IiNq#HEk zv@;?jIbA#UwY7!lJKTf~ayKCar=Y0LLs$Q84{wObpp(f%0T;JC(pZG|(Wc(-w)SL? zh2VyUKTEkhwUaF%F zf8JpYVe>Mzqr>|*mg(SDEwx59Y_oBe3bZN-Qy)~@O`{;QscBgZXC`DOvu7CSontgn zHk!&SFt+18bWD}^2uNt?x%kxDsQSatP26gjpjdGB?9C&WF{WU0VWu}%K8#I3=A3AY zT5o`t`uli?Yc_*uMGwFtnV}@}3)GiUO1(HXEv}E=98n$R*QnWGroOPvIZxPHU-GX{ zPf@LJhx-{_lA`>od8b6o_%7Cxwr;amv+`>F0!&e1ZG3S>&D(jk78*iqJ2+kUhUf3A zJh9Da{YEBs%Ixl=n_N^i@Yaff)vs6%0fyaCDK0BnVVd?6UN zHQW3AJ)aO`6qz zNyBU1uVmF-+jPgxBJ9J#ij}nANm{nn39|uq$RG9JHQ9X)htQfp5y+6IzE2iO zLRoD3IjT5k@;yAl-jcYht9B{5K1k3!WAOC!_oik}7-%({yhiGtL{@MHN%t6g)G+Wa9xScv z4>nM5!IS8-!}UoRPJ3dd+Q(_^Z|%Y~)YAtu_#JHrTH# zUQIjAx7CL!X;W({5Pj9Fi=fA%sUn3Uy4 zQxi%i3i3G^phmdt)L{3QBdK7=Ii;iHOe~RwCzvfbOUeRRKV$zH({k*g3Y77V#_SED zw%1-We(Y8Cm0-;yY?5T<3;Co2canQcI^bZ=?DCO1g~4<|+GW6-OXf#QC;8}NK0-9Y z4&Q~XWRMIz+Mj&UMgqGLU%Z(y{j2q;d{J_wT1l7=Vo%Th5n*MxjH^7IOx4enoCc2L zu03WUKHhM8Ds;ZE5Xt17Q+o)K<|wHHqF6mC0J)3f=BxXPlDt+!nAAvW)>?;q!k#~z z^LJ+%*Ot$xiVdYg8<3b5*IVtjc0(wWH)zF2R6mS97a1Kzhsp8kkrrbM1?9oKt56mg z*E7`TqH9>~iJxPL9gEzLJq|Aj<#N}bz29WGLv!w>q%Fn2ucky|>wEmz+u64-qW`VP zAaFzyU6Ss)tCj760_`Hn8{-_snoEcd-ji#@IM!aQERBkPP?a*6R84n-5hwVz-9JTI zdG||Y)~O+l*E?w>2j8t4`0ajVwc`V)aF^7&783O=3Olpp)6?8TuNElU08wb7Q4-b7 zP|5}yl2Guu@fA7TFuVvnb0@p5Int+KlE9+rA^IQiS{sXGs_g{ab?rg+=m;Zl!k<2<83LimkN7k zWNR{iOMjj?5ZJWjy1dkHcI*loG}ps!LWIc?>GuOwAyz!$%?g4i?_&WuAs7n~wIq>E{wg6Zjg~lL1E%*1QL2R6tEoB7@X$ zVg}W(97X`{o|rFVpnHYLgvzdGvSZYYu7u>m3qSSIBD5#Os+wMej@XL9A_|7s(LT|~F z#=VtNj0Nlzw#cOXlK#0V7cP}x2t9>VVpWWAV+m-v_SVJrOJ4h*_6AC$Ak@)`Hf50> zKs&lgh3q&oiMwhjHIF&$B!aJwA*?toh=#y>5n=-G4vz@#F$r;VZxtf>Bj8HJ7>d#f zlXd|S2oN+$-=AQ1QsyGNZFkL_7<>yZ79(m?&PU!sK}@TOhYa;U{^s*1gcN5%oQE`w zP_Ft=G1gZki}=v8&kkz{EgDnRiDdY`a+soPuW&GNl$tD&v|+cgvJ_yhced-LJ4ow4 zm4V9Uy)u0wQfF3qm5+dklche!%;r{=B!51plj=#v3--sx)x{zL9z}QoX*I!)5W;QAMJ-b&ct_;3QXBsfGBx;j6aTCtx3GhP(!zK=19Y43&3FsEOn!&9#Ww zKe8uFo^%DQ=pJx*oA~T#nes8m0-FJP==%FdTvmi6m#7K21V^e=IH`ZBr%|v`b8Q8h zBtwUgRVjv3BzX;E$1)|VxDrt1t|=$Y(nA&`^@D2^9WUoa;l(fz`KlTTc{a}=&bg?I*qjk5J3lKL z(_q~D2_Zq`NmQBnBW`Q6g6{|OW<;)Oz@RMM0rSrV(#urzCg!Nnn343TF+AuHPGatA z`UpMa*RQlJF&2<~RBexgN(vuC)FO6yAMxV(f<8*YDW*!P&=`A?+*P3nSS?xD3_ZmH zP484;F8W-l1%pNbQ7({NP5pR?8XZxLwBRIVb_eeh~l)l_rvXa-}Eo2P}vr$akm1mj~o2!8bo)y61jPJ_4G>;9!j-JD8z zG-N9~xbyvL=@5sSBq6ebz*w zP7$TGSb8_#DVhR}AC#=h`46LwQ>jc)51gFOOQ1zZ{2ru*q5Doop;*7--I0XwB7aft zBFKIGnm{gX#~_*HF}p{QHc|VHEtzEAiEWWYltoYXbG*hYQ?V4-$ed<<5}nmjz<9OF zil3dMwsW9qpIrscyd^eK@;&7g?QRl~D>_V-3)_f-(-=WtKjFSyQp(s+(Ei=KYUL2} z=l&X(!5Mg$d2Iimyit)O3nRNq-J~Og6Pwge3&akuQo>>)lEH?{(f7XM&T5@ZEv86- z$zY-*A(flQ4}^YZsG7CWxp>}Y!@@Hs^xWQb&4k9y+NN`q+49U1%*spBTo95^%6zlF z5>7&NTCT>#!Nwjq<21uHJpBx!9V$qzZ|9G^6tO@1is5aJZP}4(m&Z91am}UmV+KsQ7cNJndCr?9MCF=U zv-c$2hac&Nb1@>Yi21RT^Jq$c=0{Rx_J*kT3ljJTqUg!N-r=s)>L{;i>MA$Z?!8|r zTTQI_PL54ez+;Y1npw_r?=5c6O@Sz!*&Gr*v|&KN!(z+iF+wFO5S%35^{e>?X;p4e z({z8TWbP?!StBo&=A|iXXsj+SlooEE9(z%VC5LlpQ*{^K40Oio5=VSiykk)1rum(N zf)wcJ)%&SiiBfUEDt7x~!)es0=h5H~k5x!ZSex4%a>J1i?+qs z2S%1+kP}VR0)6`7^6TM-&BxN$st2Wi=OtyYSw88H)xRc4lhV#U4R+Wf*?Q$%KeW2_ zo-Mo{VxC>&k=C@}8;*h8tV}Ag9U2R=5%nr2UB+cbfL-yCFAez-8SQY+7%@hjka=O4{ zf`+3)4qV>p-1bI;?!3f^Se}bFvg?VqNOQ%-B0#4c=USMkth5dDCq)o~h*$Pjti6*XV!SjjvzKpB&$=sWx8jv59AI z6Av_2u!#PI$uPVN;nRx(-*bl^Qr{Ux$=z+6KXF$5PjQPm)pNko_9OXH{DZ%)_>y8C z%+EOV4LR)n+Up`VuXn0gP92KWSQgx1e816Gzl3`as#E@z`){-gl?1L@xW5K+zm19s z=+=0P_$TW%mnp!u^tS#bv53ZYI{w`+#%4+TrX$~_+fzlV-*n4!r^uUUF{>M&8bg6O zgtYXq-+7c+&n%{*_xkNmH|biyrRi(Vz)L&DljCjQ!R99M^=o+DYqP+wbI!RdtLtv7 zSNP-iCE_aqAB&M;5B-Q2?^Oe5-Ik#c8imPl$- zP~*Av_;UD|irdir@_4eV)!5SY@cY!pJLUC`ib@>I|CYc{aC^&hNXDaMwazbNt+kp^b<|EcUdqnhfrcBKi36hVqeQF;dz2!yJ1 zq=O)#i}Vr@F!Uy%^e&x%Qlx}lLlcl*CG^l+DAGF#aN~Q<`Mxv8{c*?rv&YKL*n5n% z<}=%~=9(LQ1siDEIF4*E_Ma+OgdAf}(?Gu-QgWaW-@Vy&$ua$v;S0>^I88BxMLxai;JS}J|r zLtTwYlfSjz74?J9r-CguorhPugiX)&BnEFjKxXnX_OJK?*LmBndjO~u2<@};rDOMJ zhknQ!3GlqTBYn@vOZH)l5T?8%+fsskv_>623Ab{APg(n7J>!n!0J@C0FSXUXlzXtJ zJ6&Fr!GTh6?5)GtTg0riRjCR?PdCULS-d1na%VYJU$v4eBg~`2ew5y6scpNmK#2LV z1ErK}sY)}M*knze<|7Bnp7ytk)xv4(fE4rAVQ>H%b5*QvP!A|EX!9nmm~6gjy9FTQ zZ&rW{&Q$Z~H`$*21b6Uu3iUbmrW!D~Z0E1HTj7nZn4IhuC;3jF0*goQfFHBH2y+?} zxlya|CHM`3QQEAq1fTTvJk;OkRI{>0>Xu;PGJJQoY)f|_sV@>ldp|OakOn!LUmMy-(RyRT1Xd6vw44em*^S)&?xR<#^f1yg!+nD z+4MQ%rGw+@L`37XzxnlNlP(mA+J28P{M2N#c|Xn757gE277_UiG%uoFsH??2DhvmM zI-BY&+6mh4D4dsS^E^X&lqZ0jCexgvHDEh_j%n1A>$MBj<_|Hpa$vPpFXb}R@5F;j zBI&O*Cv5KtCMdp6S4^ChR{74&&@))IZv?GzF!y`?Gw?iH#0gQ|n%rIwqm%-4Ro(~z zc}X!x+cYOmh^6HEwtMWY-crjZV4qZcFaZDAsRqg%_G0)Me{|?24|}z`yTIM=NVYm6 zt_-~61&YTrdA1C?PlIy%%-$7xPvZKJfk)8I#|xuh7JAES2Ww^!2^IJk3ks=a0-LP^ zI9neV9s>o`koEEGWkG=eeusDXuLZFQso$W{=<&i*o^9rE(W8Ezf<%#=ueh!5+Vp}z z&NX*#Cz?_AQZ56TT_bB{xMkswB69Qv$UBkj=_pw3sus3;*A#q)m3kT~s0>X4`^TZANI z#B;D=+Y|PvXOhSPqOy2g+={nBhA8*%AIRtoCbG#wFQ+Nxzj1m4*-Z0@AMx2Kj?v3l zDJF=;Gy>V~nq>+KmLcC{EEs3D-L7CbYD*3c?Sih}@1&5E>O%veZhohTqn;f=8$TGa zULr1NQaxSEGnKMmUVcZX`5Ij^^{!o;uH|?Q{Kzvd8*@G3P&eRSu-V%7#bB#)TEESc zCB7(m#dOiQJ5v2i<5#pL2XcG-*c7cHl=xF%vsqeH2gPhbnxJvYaU|z8oCI+~>lW`i z(K37@Fy7#siSc4(czx#zzEIK~F5CxYsWo?e_I=dgLKg@h56m);rZKmxf!uLRw5i

k13e6|I4G9%W}j!}EgV?knLnS2S#oG7_3KzrNf2Veu1m&}it&bjvij1eytBcEmmY-Ci)N zOPJ9SNpnRSvmrZ{E@Rh#RfI5!Ee=EM9tmjwk=Q-5z=-Xi0YX5JGJ{-LY@|+VEGZy7 zTWpTaw5HL?_Pe^nb<%GRR|ZC>j+fu%E+N=Ox`a%=+?U^ZOFnN7M|@S_1%3su+zrf5 z82^|Mpk&{kdZoR|i)mVjNOd3(npuBs@Imb9&pXcxf%y_sHO2$=GNy~&kq@9T!yy}9 z@jxHhkw}g?mFiC&l^w_5HrZXLB804WF0W)0B4dSL5>L)B1oRJmsdJdwc1$K$F-$#* z^{{&3^MHV1cwEW7ocVo8wd3vSHslGHaCXaO$tE9FRIs%;8G(_Xeg?FpUHbMe_%%;;6?&1zF^D; z-do7eY=b-k2dD#Npnhq`YM*}C&7pUY_}1)#LOW-E#3Zk$@&(HI7EK{SuR5O&q`^OVT!YfH}A3_lDqGPZniF> zVX>`xu5)#62UE^Q@J&P-cj)-LxBHeFs@l&L4eO-U5Y!T$&&ZQzIj}e+kq*iiSp}YT z(x1**7ZHCgjY_)l1Mw!HL|!vaarpl4V`GND_qn$Xmt1pZ&_L+ILr|%+2lY-9?Jsy# z$y*c7`?vkRZ)|R+Qcv6LugT3ODkwV2nQ1ear>4-)v%&X6+t$E(tuG}5s*A%i+bSii-QMEOu85uf@6}$y*)Kns=9JV5V)kyi z?(c0!l`daKplsM+5eoFVGJoEYQoVewr4_$lA9lIV{v&;|f?`ee9=(gUzMj)@%hEx) z(OSOWsro^qe8^ek6SuBMj5G(4#$XnMSEkh26p>Ly`hYIxOKN7Xq<#J&Y;$COamg~X z>zS~7+IaxT(9s#@Y){k*@7Np7E)5z%DppON2HO!*2&INq|3I$EGe6$Hvf1!HWJu5T zru+A@t$W)&PP*O^| z@agqReTk=+-tlYu`J!|)5XyP%!zD%a7}VG8^k(l2?MY>!Hby#D>4PiTZdHfFv^J=@ zKep@47BgC+BA)%_%0PA1gT0LS&$|`%CC*s|dhu6Bw=lxn9(7yDUJLLvN2$uoWFtcK89x z6HS_Kmq#on{+`QzAIAL12Ei#qBF$(dRB^0Wl)=B(P|Pqo?~!tIRm-s0n~4PgYVGVD zN~SpDvHKf0nOi#8>8sx2$(wcG;OAnxKoea^?C?jQeX8aPj^^}2k3=KyVs8}nuOu`+XATENO6=-b#2ne4^E$TEr*BfGQ6TUHyFws$Rr#g z!vOsX6E{!ZV!`IlhQ3c9bepnFUuqxV^4&=^L@+P{)Z{eW47;g`b`}+-G_AY@ehAIh z4n5?C7BYc7)`PY?$>uw2ig%uJLg@CR@QZ zzbYhBI(TirBm6ph`mWq+q4`Su@do+cF-VeJd`N>iM| z61+4k9PS@qZgcIb-EYwrI^A_WWXp%FT9<6EtQC1yt+3-u8n!0~bMj8dEcJOiALY!c zdg^3^rilz_(rOHkLbqIwW?;jFp^2+7Y01pY7bP*Ibw8@a^vR)AnVIGJZ(OPpwSDeH zmu|7z0Jq3YSy**vLq~tH)kq3t`m!_`<8kt4?r?@ACTAa6w#N%}m-AP?G?xaw`}9f^ zJ6iVWrF@)Mr^$mIih(rpBieOC$nK^>$H%-<+rUV>)WtvZa@kRr-1EPl$%G!|3EhT} zy|MIfSqfWulaP&O^m4ZUOcr#xQ_w&DRsY?MZy=mXqf(z2=dP;Dr0}!n@s2{UhgIi2 z-I$Pt-9vtR{iD9rfUDPBsR2L($_?o7$NR?yZi$5J`W=|bm_JA3u}HhX8*hSivMcEP zk+0UM%)&Nn;LRh%_HH6{(LASv(Dl^~YuR3am;?XRvz0eL^;@Q0+^69N1gGy$zc~EsFvi0kBB~b@(yOsO2Jljn*)etJ1q zdSQ)A`dx3Qac7EhD(IN5An*2nLEVkT zX2)ABHruDM*bJ-uu&mPeF%RXhl$|k~+bHz)B%!Ta)U+1u>ad=dF^f{2qi@vgC zM|roaR4(auhPX=Bjh)mP^mM_J7NRqh5_~sSCL>ZPTpS1t?m5HEC4!B18nLR(yR2VC zqdx)?(x9y$*2>vxIGy1?A?$+v1*vn^3s_9__P;^uoP`Bx!^G?F`P+;RZ=lu1q&B8C zceERD^~M}{8-P5{ek`5Fc-*|06Y;pQ#}-NXEd8obpW-fJx9;;LexvTFQAhN#f z|JA|mrT3=|S$8u_4RUPAIBk9$g#YZr;!u8REwjj<-X&qYlSiy?HKN{9mAI#7Ln=~* zW6}Y^zGXrbf~2!)?<;&Z_{QY}9C97vQZ=mW&jtYfKIwQgPfi2zfSje|XpsZlXvz0< z7Q{Zfq{wSZHoRW(`1z>`o1u$ihuE9-G3~kxbG0uGYEIUuU@G(ScsN+d-osbh8jTu& zm*$ud%6aZV)*6ejlYNr&p;*ny&gzM5gQ!Rm*pT)ENFDK-W;XAwW5{lzK|&KN^IZOk z^W5SOP+#F)TprU`MEH6x`S`dz(=qtC+y6+@baGwsIn7SbE*mb+i-$ip>dI{DB$+Sj z$}07lr747LK#aF_0_l7)6P+jzqbXy47zsWRC(gc-P*>y6q}<7MSm2NmI?!!d(%Mbl-0ov2fM$7}9!oUhaMbh70QGYP4^qS{LmA`V}D(qC!f zc}TLkAXtRHH+~c(s2~Wr^vx>!0BgxwNl1E@A!!CxS_+#SOC+C*gNNUBR!%B>*pN1s zn@BXLW{gvU2T0bnvVYBs2M8NjP@6ixEVp;1!4q=Af{xV>qFslnSBxd-5}y5Ll4sL=aQE8}*~JT4!>Gk3`u_3+Kr z238>GNzPsRyK&slhI~fS>$VIR`@m88ND$wK!{wm8lr zIYQa&f6YI>(CHhNOe}R08#({6?!z5zsffSmK1O$|HNU3ZoA}ov$|Z~#uNfXv;vSVQ zslLp{E0xR3GrbDVG^9Tk*&I944cvss|8Ob z<15Q?QmC2GRKWwP=jiyQ;3V1oKzYS>_XX20>h}hLg^#;nqQ-s?UA6|v8rW)2B9GU* zJRZw5G;b#YcGa)2ji8y+i}Y9BAji7!nbV|#R)@%eLL~SC!${Oh&{$5rQ~OqVujXLv zE@!l^Dtq@~#cIUONFYzESR2k{<6$lT+{#fyXv$Pu-a6zoYSB0oFTr%7V8HNuEo=Mf zs1y0{bieO~k;Wszl+Rh*7!OokPwkwzD}HsS{7i+$?wnZ}SYWm5?5EVt{7X1TuSo{7 zx{-EL-K?OXu7VQb7C)e(JW?7PVb@1MVj^g`qbDr=aaO_KSWR*S`Jt&;mViz&>FIO-2Cq1%Gy?68?i(tVijxg z4C{U8&)BrH$Ldf?WLdxJ{sL?ItTdBH*9b%$Kf3^;RUe6}uCRyarKU7nbPK=qgyt^Bo#Dyd_*5rzfGI?HEg@mu5VBytG{RjVs$SaU66l=RnN zIcw|xHCVJ>I$2bt)qacX_d&zytq3(@RK8HlMz&0BQ?(sG3^!Qw1Gi|=HCG3#b~a^4 z##pX>2moGk%2lfB>FA4!9M5Q!Fw08`bPiT_KFY)#Vph&}GCciH3wN4I1Q!03FY1Z6 z72NwqDJ3fKd9Ku2$8)I0JzYejPEAz*(Qh$oC!m0L9@dg5|L%6-@Giv)Rtg(fWeR(vobK7})NR1J^aaxN84+p@b0-|XlTghpB1@sptIDWRhjg-NXd)4+nNP?c( zC+rB=UMirYa_wmTgQB$oS~vW*vunHM$fS+e|- zivW2a`E2GnuRNf+x2~e_mIG^~&PF-Q024l&|FTlwpHwY(H%`8I1UmR}zu`^g6uoZ= zSDu5nkm*XVHpQ#`vj#m8-pe(vUM!%#JwY@kU@tQ<3NMTQ`oof0xpL-u#FyZ4UM!m` z2mRhrSovAn29(v!bX8j9PwBIXxHI}oBCol=%pom0%La63ry%~Ipp{hH@OOQyjC1L# z-F-LeFVH;`nPn#L{E}w&22*!Qg-Ld*v@^dENwCO{PrlDqp7OACqLjPNYv>^pF#nn$ zL@7s-KSXJNl=x4suJ;Qc@~o4D>()2mMJgc3hqXWUvxaYd%YbSA4btHnY z$pyl#nx$+89h%z<)ls>A7PYS`yRIfPAx{``Y&wk!(0PUr&2hhln;_02dLG6^e?LEW zhBk8a+DOM_V<;(OvImpHzH?SHcKxpX$3YE1crBHjmy4O#H1wn?IhYDSDuEcV6>d*N*J@`=4@M18;t=xo;IZEKN784>EodY_};)Qn1YTiacx6a@C}* z9!Q%-3ld~ijDu2&$kXOMU2JUybvK=&!@sUZ8 z7q7@f3kmd2;`(m^3vig8mHT!EYkmW#FVI=VKECy$=gj4~c`=U&=+BD;)?ZgH5qVyu z1?uR$)?`l7fro$6!Ok^kjF=Hfs-?O$`c&3#{%>5Ys#T1fb}eE}9DY>bwZ_LbRatkK zkYS6qMY4X$nQ zle$tj6#XZhLoqg_eeX~rpX&{MXpH{DX+Pj5HLqfb^H;o|ZKxM!c58qdP)+uw7o-jv zRhue2$Zm#%N@70vg9H(vS@?KO%bTJ^eWr7GDChG{5gh2fattw^bh5x1YkO@gN!EE| zoE|x=vsGuhDcj_BnH?}IST&dKV20K#SBN>XJZ>`_!k6F~-$9%3ur;UFPxT`Bm+POH zF5q3}ReMs%A7NjI%?*PIsExVXgR$PJ zJ@_92qaPy2SDGy{qzQN{Bp1XZ5a#JTaBQ(3_(WevOz&&Y-wgN-yS4hM4c-;X!EWAz zyqm5s<7+#wuV7cvmeC6b*Sc%1@G*`(Xcj zo+LRZywU&vY$C+khkH!+_{SzO9nmO50ob*^RQ zjjIk(s8er$T%y{YrkN+RK=v9f0o%Uan)h*1HG~iP64!z$^m67P?4dv%6x2|sH%Pc` z4@AW4zKFB-Kow_)%ycE|&VglV^tUZzp`I3+m2ifjbTREvz->t1)8w*C)^_%JHV30l zd@yzDcsni|5OYw9yb20o)v1<4liM%TWVJyIL_G zn~Cu~gLitl^eGM`FM9mm!(G$8MntHhlU~6o=%*NHzw3AdoYR$$(jv8aO<(=|fkg>j zZSXFUA`JC6Y75bhKC*aV&CgUAsbgb1>YjA(-6TsOsyJ55{nepD+3u5?L&86Q)Lc}z z4wn&R8-opr#p2H#o_R`d9%-c;5ePK)bKbQCnE`%eQ4iMVS}7vw;G4;{+dr0$!uiBD zd|)Nfq_;ZQ59FG{Ze*gpEvXLgGk!4m$w&_>3t@~!JGu|(QVjNvZ_K9rcezS-k0?JZ zpR-N<^)?4tF?SLtK{2*<5L=y{3M25RsM9~Rf+|twziU|V6l-=K9+y2RU2Zv!nB?ZIZg1!~&h6@Wc{b6rNb33qKo6bm9I(bcueTS==;4U_u_awBWwkMX1{G6M`4< zpOPB<>hk89*!TJCB5n%!8;UQ)5oppDETjFyU-s>}^ z;GM?;-*(uK+Z_sO9q&x3rh4AhtD5k;pDV6cC4=>}>Svs_=4>-id9(OG%z3IEZX;Dq z!|pZl3J7)@%2@sSXd?fBDw!-|{u$`_3?2s>5hB4p1O0XQodd1g?Rezt$E3{$daWrP zA&)gM3M^Oy^UzN9vj$6quq#1n49lB;h|wsPM>F+vbOgQBz_v9*PcwNP;4%Nz5D|jI)wz1d>i#+L^R6~Hh<I{DJOL5X&;1W$0qX$;RK--xeReRf+Lv#XMhf{+G`B+YAv>5<&qJrb8;C9GXE)e( z)Ww?hm;P=Z8J%~<56-SnowCElU%iMvMEi6wF399XUYx&4Y`fSinGlpgHrwu&1YDpA zAFLJXmn`;IULD|z28{@mJCDp(2bdIOtj}1%;jKXQ3cO{&B5Zv|-8-N~5-I$_!qnT0B$H8_XIucxsS?9;B!^E1Jn;N~*`%^Y!wfyNqs{h*b zB5~@SVv?Wd;JljloMP7He0(O(d*ld3nRZpCZl@y{noaHdiok z?xm$~vCBQH>ad9IbZYwfVmW01**tT$KJnZ{l=mc0=F-~B4=pfn+)Z*(77jq|c0y$m z>TZ4dG|T4i-ajWB`+VJvhIQ>$bYEMqS+DL^N5%*K4C^E}92YlUiJ0&TPMQ@dvuTMk zN9aX0V)V=>#pk)4YnQioX;A|tKcl?n{uU?%V0VZfy3E_3_I+M-9C2nevA@Gttr&Ti zqK436E8%Yyz&tNBeR_UmFQ74U;5Z-#kTPX}+O3~5fs6e-DG)XnYJtAZy7?;63eHkf zY^0MI2o4PzW9sfjAz4Fg;nPSWjd0JmoI#dfdmw(W(Keieh zALYLD_D}9b=nnEW8z(#I4PHE*XlCrYNYhvLlFSYJwG&7zLTy!c&Ndz=_Dw`l^jVXD ziK*b#@!|}&CgGiz+qnQg-2LN!cBhM?5f=G4B~Sg`<`-}1!DBWuexoBjURL`75^asG z-q&J?yBnU{txZ?D-n4>O`&S0zw5S#;^cLShy=q`lDhRqblm_|~5|ufxi+N@h1hd8aY(amgV%APTsN((|$Mg~yp$46e5&A$Kd SpLhW`%xuc+vUj)$?))FB Date: Thu, 27 Jun 2024 15:00:41 +0200 Subject: [PATCH 09/10] update tests --- tests/test_term.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_term.py b/tests/test_term.py index a60ec2b..275ff41 100644 --- a/tests/test_term.py +++ b/tests/test_term.py @@ -10,7 +10,7 @@ def test_lt(): term = kg.ontology.terms.cmso.hasNumberOfAtoms term = term < 2 - assert term._condition == '(?cmso:hasNumberOfAtomsvalue<"2"^^xsd:int)' + assert term._condition == '(?hasNumberOfAtomsvalue<"2"^^xsd:int)' def test_eq(): kg = KnowledgeGraph() @@ -18,7 +18,7 @@ def test_eq(): term = kg.ontology.terms.cmso.hasNumberOfAtoms term = (term == 2) - assert term._condition == '(?cmso:hasNumberOfAtomsvalue="2"^^xsd:int)' + assert term._condition == '(?hasNumberOfAtomsvalue="2"^^xsd:int)' def test_gt(): kg = KnowledgeGraph() @@ -26,7 +26,7 @@ def test_gt(): term = kg.ontology.terms.cmso.hasNumberOfAtoms term = term > 2 - assert term._condition == '(?cmso:hasNumberOfAtomsvalue>"2"^^xsd:int)' + assert term._condition == '(?hasNumberOfAtomsvalue>"2"^^xsd:int)' def test_lte(): kg = KnowledgeGraph() @@ -34,7 +34,7 @@ def test_lte(): term = kg.ontology.terms.cmso.hasNumberOfAtoms term = term <= 2 - assert term._condition == '(?cmso:hasNumberOfAtomsvalue<="2"^^xsd:int)' + assert term._condition == '(?hasNumberOfAtomsvalue<="2"^^xsd:int)' def test_gte(): kg = KnowledgeGraph() @@ -42,7 +42,7 @@ def test_gte(): term = kg.ontology.terms.cmso.hasNumberOfAtoms term = term >= 2 - assert term._condition == '(?cmso:hasNumberOfAtomsvalue>="2"^^xsd:int)' + assert term._condition == '(?hasNumberOfAtomsvalue>="2"^^xsd:int)' def test_ne(): kg = KnowledgeGraph() @@ -50,18 +50,18 @@ def test_ne(): term = kg.ontology.terms.cmso.hasNumberOfAtoms term = term != 2 - assert term._condition == '(?cmso:hasNumberOfAtomsvalue!="2"^^xsd:int)' + assert term._condition == '(?hasNumberOfAtomsvalue!="2"^^xsd:int)' def test_and(): kg = KnowledgeGraph() struct_Fe = System.create.element.Fe(graph=kg) term = (kg.ontology.terms.cmso.hasVolume > 2) & (kg.ontology.terms.cmso.hasVolume < 4) - assert term._condition == '((?cmso:hasVolumevalue>"2"^^xsd:float)&&(?cmso:hasVolumevalue<"4"^^xsd:float))' + assert term._condition == '((?hasVolumevalue>"2"^^xsd:float)&&(?hasVolumevalue<"4"^^xsd:float))' def test_or(): kg = KnowledgeGraph() struct_Fe = System.create.element.Fe(graph=kg) term = (kg.ontology.terms.cmso.hasVolume > 2) | (kg.ontology.terms.cmso.hasVolume < 4) - assert term._condition == '((?cmso:hasVolumevalue>"2"^^xsd:float)||(?cmso:hasVolumevalue<"4"^^xsd:float))' \ No newline at end of file + assert term._condition == '((?hasVolumevalue>"2"^^xsd:float)||(?hasVolumevalue<"4"^^xsd:float))' \ No newline at end of file From 6c462b067507f12111024e41da6dcd33434c3ca0 Mon Sep 17 00:00:00 2001 From: Sarath Date: Thu, 27 Jun 2024 15:01:44 +0200 Subject: [PATCH 10/10] fix or in example --- examples/10_sparql_queries.ipynb | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/examples/10_sparql_queries.ipynb b/examples/10_sparql_queries.ipynb index 0ea5606..e197016 100644 --- a/examples/10_sparql_queries.ipynb +++ b/examples/10_sparql_queries.ipynb @@ -723,7 +723,7 @@ "source": [ "## Logical operators\n", "\n", - "Logical operators currently supported are & and ||. These operators, when applied, aggregates the condition between two terms|" + "Logical operators currently supported are & and |. These operators, when applied, aggregates the condition between two terms|" ] }, { @@ -746,6 +746,26 @@ "(kg.terms.cmso.hasChemicalSymbol=='Al') & (kg.terms.cmso.hasElementRatio==1.0)" ] }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "cmso:hasChemicalSymbol" + ] + }, + "execution_count": 42, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(kg.terms.cmso.hasChemicalSymbol=='Al') | (kg.terms.cmso.hasElementRatio==1.0)" + ] + }, { "cell_type": "markdown", "metadata": {},