From 10d37298e1b8542d305b811d807564eccc85f770 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Sat, 4 Jan 2025 17:04:17 +0000 Subject: [PATCH 01/58] Add semantikon to the environment --- .ci_support/environment.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index ef41085..8418edd 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -5,4 +5,5 @@ dependencies: - openjdk - owlready2 =0.47 - pandas =2.2.3 -- pint =0.24.4 \ No newline at end of file +- pint =0.24.4 +- semantikon =0.0.5 From 19876e7c6416f9e6fd8b2d738b1bf9d2c9ecde6f Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 6 Jan 2025 17:27:38 +0000 Subject: [PATCH 02/58] update environment --- .ci_support/environment.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 8418edd..ff2e703 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -6,4 +6,5 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.5 +- semantikon =0.0.6 +- pyiron_workflow =0.11.2 From ebd3380bd5202772e1e8d3c1dc62cacb10e79437 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Mon, 6 Jan 2025 17:29:00 +0000 Subject: [PATCH 03/58] [dependabot skip] Update env file --- .binder/environment.yml | 4 +++- docs/environment.yml | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.binder/environment.yml b/.binder/environment.yml index 42d4747..0a11c8e 100644 --- a/.binder/environment.yml +++ b/.binder/environment.yml @@ -6,6 +6,8 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 +- semantikon =0.0.6 +- pyiron_workflow =0.11.2 - pyiron_atomistics =0.6.19 -- pyiron-data =0.0.29 +- pyiron-data =0.0.30 - lammps =2024.02.07=*_openmpi_* diff --git a/docs/environment.yml b/docs/environment.yml index c507644..c19fd5a 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -12,4 +12,6 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 +- semantikon =0.0.6 +- pyiron_workflow =0.11.2 - sphinxcontrib-mermaid From 6e8d597c3f19002f2f66a838c9e18023aba24b44 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 6 Jan 2025 17:29:25 +0000 Subject: [PATCH 04/58] Forgot to add the parser --- pyiron_ontology/parser.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 pyiron_ontology/parser.py diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py new file mode 100644 index 0000000..933df6b --- /dev/null +++ b/pyiron_ontology/parser.py @@ -0,0 +1,32 @@ +from semantikon.converter import parse_input_args, parse_output_args + + +def get_inputs_and_outputs(node): + """ + Read input and output arguments with their type hints and return a + dictionary containing all input output information + + Args: + node (pyiron_workflow.nodes.Node): node to be parsed + + Returns: + (dict): dictionary containing input output args, type hints, values + and variable names + """ + inputs = parse_input_args(node.node_function) + outputs = parse_output_args(node.node_function) + if isinstance(outputs, dict): + outputs = (outputs, ) + outputs = {key: out for key, out in zip(node.outputs.labels, outputs)} + for key, value in node.inputs.to_value_dict().items(): + inputs[key]["value"] = value + inputs[key]["var_name"] = key + for key, value in node.outputs.to_value_dict().items(): + outputs[key]["value"] = value + outputs[key]["var_name"] = key + return { + "input": inputs, + "output": outputs, + "function": node.node_function.__name__, + "label": node.label + } From ad45af4d6e5d6a7ae3f6373059a1d2728ccff1d5 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 6 Jan 2025 17:36:02 +0000 Subject: [PATCH 05/58] remove python 3.9 --- .github/workflows/push-pull.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/push-pull.yml b/.github/workflows/push-pull.yml index 55368fc..63fac5f 100644 --- a/.github/workflows/push-pull.yml +++ b/.github/workflows/push-pull.yml @@ -12,7 +12,8 @@ jobs: uses: pyiron/actions/.github/workflows/push-pull.yml@actions-3.3.3 secrets: inherit with: + python-version-alt3: 'exclude' # No python 3.9 docs-env-files: .ci_support/environment.yml .ci_support/environment-docs.yml notebooks-env-files: .ci_support/environment.yml .ci_support/environment-pyiron_atomistics.yml .ci_support/environment-lammps.yml tests-env-files: .ci_support/environment.yml .ci_support/environment-pyiron_atomistics.yml - alternate-tests-env-files: .ci_support/lower_bound.yml \ No newline at end of file + alternate-tests-env-files: .ci_support/lower_bound.yml From 09a09e489ac74014f0bd3f24924197728dea552f Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 6 Jan 2025 17:47:59 +0000 Subject: [PATCH 06/58] run black --- pyiron_ontology/parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 933df6b..e71bbd4 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -16,7 +16,7 @@ def get_inputs_and_outputs(node): inputs = parse_input_args(node.node_function) outputs = parse_output_args(node.node_function) if isinstance(outputs, dict): - outputs = (outputs, ) + outputs = (outputs,) outputs = {key: out for key, out in zip(node.outputs.labels, outputs)} for key, value in node.inputs.to_value_dict().items(): inputs[key]["value"] = value @@ -28,5 +28,5 @@ def get_inputs_and_outputs(node): "input": inputs, "output": outputs, "function": node.node_function.__name__, - "label": node.label + "label": node.label, } From e6d90adad37222ba361fdb200e1295885d710990 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 6 Jan 2025 18:18:02 +0000 Subject: [PATCH 07/58] add tests --- tests/unit/test_parser.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/unit/test_parser.py diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py new file mode 100644 index 0000000..0d5ede1 --- /dev/null +++ b/tests/unit/test_parser.py @@ -0,0 +1,24 @@ +import unittest +from pyiron_ontology.parser import get_inputs_and_outputs +from pyiron_workflow import Workflow +from semantikon.typing import u + + +@Workflow.wrap.as_function_node("speed") +def calculate_speed( + distance: u(float, units="meter"), + time: u(float, units="second"), +) -> u(float, units="meter/second"): + return distance / time + + +class TestParser(unittest.TestCase): + def test_parser(self): + c = calculate_speed() + output_dict = get_inputs_and_outputs(c) + for label in ["input", "output", "function", "label"]: + self.assertIn(label, output_dict) + + +if __name__ == "__main__": + unittest.main() From e43109e6dfff5a71506dc3b432dc95e04c2868c8 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 9 Jan 2025 09:03:09 +0000 Subject: [PATCH 08/58] Make input and output plural to be in agreement with the pyiron_workflow definitions --- pyiron_ontology/parser.py | 4 ++-- tests/unit/test_parser.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index e71bbd4..f9eb912 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -25,8 +25,8 @@ def get_inputs_and_outputs(node): outputs[key]["value"] = value outputs[key]["var_name"] = key return { - "input": inputs, - "output": outputs, + "inputs": inputs, + "outputs": outputs, "function": node.node_function.__name__, "label": node.label, } diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 0d5ede1..393458b 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -16,7 +16,7 @@ class TestParser(unittest.TestCase): def test_parser(self): c = calculate_speed() output_dict = get_inputs_and_outputs(c) - for label in ["input", "output", "function", "label"]: + for label in ["inputs", "outputs", "function", "label"]: self.assertIn(label, output_dict) From c44652351a504576c494453887bfe51b9ebe777e Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 9 Jan 2025 09:49:28 +0000 Subject: [PATCH 09/58] small bugfixes --- pyiron_ontology/parser.py | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index f9eb912..ee6afbd 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -1,4 +1,12 @@ from semantikon.converter import parse_input_args, parse_output_args +from rdflib import Graph, Literal, RDF, RDFS + + +def get_source_output(var): + if not var.connected: + return None + connection = var.connections[0] + return f"{connection.owner.label}.outputs.{connection.label}" def get_inputs_and_outputs(node): @@ -18,9 +26,10 @@ def get_inputs_and_outputs(node): if isinstance(outputs, dict): outputs = (outputs,) outputs = {key: out for key, out in zip(node.outputs.labels, outputs)} - for key, value in node.inputs.to_value_dict().items(): - inputs[key]["value"] = value + for key, value in node.inputs.items(): + inputs[key]["value"] = value.value inputs[key]["var_name"] = key + inputs[key]["connection"] = get_source_output(value) for key, value in node.outputs.to_value_dict().items(): outputs[key]["value"] = value outputs[key]["var_name"] = key @@ -30,3 +39,29 @@ def get_inputs_and_outputs(node): "function": node.node_function.__name__, "label": node.label, } + + +def get_triples(data, EX): + graph = Graph() + label_def_triple = (EX[data["label"]], EX.hasSourceFunction, EX[data["function"]]) + if len(list(graph.triples(label_def_triple))) > 0: + return graph + graph.add(label_def_triple) + for io_ in ["inputs", "outputs"]: + for key, d in data[io_].items(): + full_key = data["label"] + f".{io_}." + key + label = EX[full_key] + graph.add((label, RDFS.label, Literal(full_key))) + graph.add((label, RDF.type, d["uri"])) + graph.add((label, RDF.value, Literal(d["value"]))) + graph.add((label, EX[io_[:-1] + "Of"], EX[data["label"]])) + if d["units"] is not None: + graph.add((label, EX.hasUnits, EX[d["units"]])) + if "connection" in d: + graph.add((label, EX.comesFrom, EX[d["connection"]])) + if d["triple"] is not None: + obj = d["triple"][1] + if obj.startswith("inputs.") or obj.startswith("outputs."): + obj = data["label"] + "." + obj + graph.add((label, d["triple"][0], EX[obj])) + return graph From cb421d12f79b3e0e9bdfd38c39d28db50e3e3dba Mon Sep 17 00:00:00 2001 From: samwaseda Date: Fri, 10 Jan 2025 06:12:07 +0000 Subject: [PATCH 10/58] set lower bound --- .ci_support/lower_bound.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.ci_support/lower_bound.yml b/.ci_support/lower_bound.yml index 1704139..cc3d75c 100644 --- a/.ci_support/lower_bound.yml +++ b/.ci_support/lower_bound.yml @@ -7,4 +7,6 @@ dependencies: - pandas =2.1.4 - pint =0.23 - pyiron_atomistics =0.5.0 -- pyiron-data =0.0.26 \ No newline at end of file +- pyiron-data =0.0.26 +- semantikon =0.0.6 +- pyiron_workflow =0.11.2 From b6c61b247d1d31ec27217eb2e8324997319558da Mon Sep 17 00:00:00 2001 From: samwaseda Date: Fri, 10 Jan 2025 06:24:47 +0000 Subject: [PATCH 11/58] Add rdflib --- .ci_support/environment.yml | 1 + .ci_support/lower_bound.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index ff2e703..94bc8b6 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -8,3 +8,4 @@ dependencies: - pint =0.24.4 - semantikon =0.0.6 - pyiron_workflow =0.11.2 +- rdflib =7.1.1 diff --git a/.ci_support/lower_bound.yml b/.ci_support/lower_bound.yml index cc3d75c..50ed90b 100644 --- a/.ci_support/lower_bound.yml +++ b/.ci_support/lower_bound.yml @@ -10,3 +10,4 @@ dependencies: - pyiron-data =0.0.26 - semantikon =0.0.6 - pyiron_workflow =0.11.2 +- rdflib =7.1.1 From 888e25bb3eaff4c2327d8aedd2e1096204d06d42 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Fri, 10 Jan 2025 06:25:40 +0000 Subject: [PATCH 12/58] [dependabot skip] Update env file --- .binder/environment.yml | 1 + docs/environment.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.binder/environment.yml b/.binder/environment.yml index 0a11c8e..e93c525 100644 --- a/.binder/environment.yml +++ b/.binder/environment.yml @@ -8,6 +8,7 @@ dependencies: - pint =0.24.4 - semantikon =0.0.6 - pyiron_workflow =0.11.2 +- rdflib =7.1.1 - pyiron_atomistics =0.6.19 - pyiron-data =0.0.30 - lammps =2024.02.07=*_openmpi_* diff --git a/docs/environment.yml b/docs/environment.yml index c19fd5a..93407b1 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -14,4 +14,5 @@ dependencies: - pint =0.24.4 - semantikon =0.0.6 - pyiron_workflow =0.11.2 +- rdflib =7.1.1 - sphinxcontrib-mermaid From 66bf6a7a4a295c14219d94478610b6de36e76b35 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Fri, 10 Jan 2025 13:05:18 +0000 Subject: [PATCH 13/58] add one test --- pyiron_ontology/parser.py | 6 ++++-- tests/unit/test_parser.py | 12 +++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index ee6afbd..564aace 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -52,8 +52,10 @@ def get_triples(data, EX): full_key = data["label"] + f".{io_}." + key label = EX[full_key] graph.add((label, RDFS.label, Literal(full_key))) - graph.add((label, RDF.type, d["uri"])) - graph.add((label, RDF.value, Literal(d["value"]))) + if d["uri"]: + graph.add((label, RDF.type, d["uri"])) + if d["value"]: + graph.add((label, RDF.value, Literal(d["value"]))) graph.add((label, EX[io_[:-1] + "Of"], EX[data["label"]])) if d["units"] is not None: graph.add((label, EX.hasUnits, EX[d["units"]])) diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 393458b..8f35b2f 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -1,7 +1,8 @@ import unittest -from pyiron_ontology.parser import get_inputs_and_outputs +from pyiron_ontology.parser import get_inputs_and_outputs, get_triples from pyiron_workflow import Workflow from semantikon.typing import u +from rdflib import Namespace @Workflow.wrap.as_function_node("speed") @@ -19,6 +20,15 @@ def test_parser(self): for label in ["inputs", "outputs", "function", "label"]: self.assertIn(label, output_dict) + def test_triples(self): + EX = Namespace("http://example.org/") + speed = calculate_speed() + data = get_inputs_and_outputs(speed) + graph = get_triples(data, EX) + self.assertGreater( + len(list(graph.triples((None, EX.hasUnits, EX["meter/second"])))), 0 + ) + if __name__ == "__main__": unittest.main() From 06daa09f77995f375a8b526943abc9cb50c68ae6 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Sat, 11 Jan 2025 09:12:33 +0000 Subject: [PATCH 14/58] update semantikon version --- .ci_support/environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 94bc8b6..685813c 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -6,6 +6,6 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.6 +- semantikon =0.0.7 - pyiron_workflow =0.11.2 - rdflib =7.1.1 From f80549b5f1991fcb447d6bf4dfcb1a14989b9528 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Sat, 11 Jan 2025 09:12:53 +0000 Subject: [PATCH 15/58] [dependabot skip] Update env file --- .binder/environment.yml | 2 +- docs/environment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.binder/environment.yml b/.binder/environment.yml index e93c525..94d5a02 100644 --- a/.binder/environment.yml +++ b/.binder/environment.yml @@ -6,7 +6,7 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.6 +- semantikon =0.0.7 - pyiron_workflow =0.11.2 - rdflib =7.1.1 - pyiron_atomistics =0.6.19 diff --git a/docs/environment.yml b/docs/environment.yml index 93407b1..cd95950 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -12,7 +12,7 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.6 +- semantikon =0.0.7 - pyiron_workflow =0.11.2 - rdflib =7.1.1 - sphinxcontrib-mermaid From c6c47dfbca4059936790c31c1395c21bd388327c Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 13 Jan 2025 09:13:58 +0000 Subject: [PATCH 16/58] update definition of connection --- pyiron_ontology/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 564aace..c706cbe 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -59,7 +59,7 @@ def get_triples(data, EX): graph.add((label, EX[io_[:-1] + "Of"], EX[data["label"]])) if d["units"] is not None: graph.add((label, EX.hasUnits, EX[d["units"]])) - if "connection" in d: + if d["connection"]: graph.add((label, EX.comesFrom, EX[d["connection"]])) if d["triple"] is not None: obj = d["triple"][1] From 770e72f64b7ec11222e32d90dcfc341bbafc3966 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 13 Jan 2025 09:15:14 +0000 Subject: [PATCH 17/58] bugfix --- pyiron_ontology/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index c706cbe..25c2ec4 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -59,7 +59,7 @@ def get_triples(data, EX): graph.add((label, EX[io_[:-1] + "Of"], EX[data["label"]])) if d["units"] is not None: graph.add((label, EX.hasUnits, EX[d["units"]])) - if d["connection"]: + if d.get("connection", None) not None: graph.add((label, EX.comesFrom, EX[d["connection"]])) if d["triple"] is not None: obj = d["triple"][1] From d39264342ddc1f642d1c35d887734e4e109caf49 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 13 Jan 2025 09:15:46 +0000 Subject: [PATCH 18/58] another programming error worth a harakiri --- pyiron_ontology/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 25c2ec4..4813453 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -59,7 +59,7 @@ def get_triples(data, EX): graph.add((label, EX[io_[:-1] + "Of"], EX[data["label"]])) if d["units"] is not None: graph.add((label, EX.hasUnits, EX[d["units"]])) - if d.get("connection", None) not None: + if d.get("connection", None) is not None: graph.add((label, EX.comesFrom, EX[d["connection"]])) if d["triple"] is not None: obj = d["triple"][1] From e22934459dd0140d37f6db1a00fa6221cce63a9d Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 13 Jan 2025 13:58:01 +0000 Subject: [PATCH 19/58] make sure that the triples are tuples --- pyiron_ontology/parser.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 4813453..0bd1263 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -62,8 +62,12 @@ def get_triples(data, EX): if d.get("connection", None) is not None: graph.add((label, EX.comesFrom, EX[d["connection"]])) if d["triple"] is not None: - obj = d["triple"][1] - if obj.startswith("inputs.") or obj.startswith("outputs."): - obj = data["label"] + "." + obj - graph.add((label, d["triple"][0], EX[obj])) + if isinstance(d["triple"][0], tuple): + triple = d["triple"] + else: + triple = (d["triple"],) + for t in triple: + if t[1].startswith("inputs.") or t[1].startswith("outputs."): + t[1] = data["label"] + "." + t[1] + graph.add((label, t[0], EX[obj])) return graph From c1be53ffeae7b1e10abb922c1d3426eee8c2db8b Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 13 Jan 2025 14:07:16 +0000 Subject: [PATCH 20/58] bugfix --- pyiron_ontology/parser.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 0bd1263..f0f0bc5 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -62,12 +62,13 @@ def get_triples(data, EX): if d.get("connection", None) is not None: graph.add((label, EX.comesFrom, EX[d["connection"]])) if d["triple"] is not None: - if isinstance(d["triple"][0], tuple): - triple = d["triple"] + if isinstance(d["triple"][0], tuple | list): + triple = list(d["triple"]) else: - triple = (d["triple"],) + triple = [d["triple"]] for t in triple: - if t[1].startswith("inputs.") or t[1].startswith("outputs."): - t[1] = data["label"] + "." + t[1] + obj = t[1] + if obj.startswith("inputs.") or obj.startswith("outputs."): + obj = data["label"] + "." + obj graph.add((label, t[0], EX[obj])) return graph From 1695fa73603342e1038355ce8438b25997c3bce5 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Wed, 15 Jan 2025 13:20:14 +0000 Subject: [PATCH 21/58] set default values --- pyiron_ontology/parser.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index f0f0bc5..d170119 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -25,8 +25,12 @@ def get_inputs_and_outputs(node): outputs = parse_output_args(node.node_function) if isinstance(outputs, dict): outputs = (outputs,) + elif outputs is None: + outputs = len(node.outputs.labels) * ({},) outputs = {key: out for key, out in zip(node.outputs.labels, outputs)} for key, value in node.inputs.items(): + if inputs[key] is None: + inputs[key] = {} inputs[key]["value"] = value.value inputs[key]["var_name"] = key inputs[key]["connection"] = get_source_output(value) @@ -52,16 +56,16 @@ def get_triples(data, EX): full_key = data["label"] + f".{io_}." + key label = EX[full_key] graph.add((label, RDFS.label, Literal(full_key))) - if d["uri"]: + if d.get("uri", None) is not None: graph.add((label, RDF.type, d["uri"])) - if d["value"]: + if d.get("value", None): graph.add((label, RDF.value, Literal(d["value"]))) graph.add((label, EX[io_[:-1] + "Of"], EX[data["label"]])) - if d["units"] is not None: + if d.get("units", None) is not None: graph.add((label, EX.hasUnits, EX[d["units"]])) if d.get("connection", None) is not None: graph.add((label, EX.comesFrom, EX[d["connection"]])) - if d["triple"] is not None: + if d.get("triple", None) is not None: if isinstance(d["triple"][0], tuple | list): triple = list(d["triple"]) else: From 33f71a6757296819c10f3117e1fc779bb9ec005c Mon Sep 17 00:00:00 2001 From: samwaseda Date: Wed, 15 Jan 2025 13:22:39 +0000 Subject: [PATCH 22/58] convert object to URIRef only if it is not already one --- pyiron_ontology/parser.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index d170119..6db5fd2 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -1,5 +1,5 @@ from semantikon.converter import parse_input_args, parse_output_args -from rdflib import Graph, Literal, RDF, RDFS +from rdflib import Graph, Literal, RDF, RDFS, URIRe def get_source_output(var): @@ -74,5 +74,7 @@ def get_triples(data, EX): obj = t[1] if obj.startswith("inputs.") or obj.startswith("outputs."): obj = data["label"] + "." + obj - graph.add((label, t[0], EX[obj])) + if not isinstance(obj, URIRef): + obj = EX[obj] + graph.add((label, t[0], obj)) return graph From 0581c0c78171505720a8c8fa0d427dfa6231ac55 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Wed, 15 Jan 2025 13:24:34 +0000 Subject: [PATCH 23/58] typo --- pyiron_ontology/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 6db5fd2..538ce88 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -1,5 +1,5 @@ from semantikon.converter import parse_input_args, parse_output_args -from rdflib import Graph, Literal, RDF, RDFS, URIRe +from rdflib import Graph, Literal, RDF, RDFS, URIRef def get_source_output(var): From 662ea1a1a0a93825711e117ad712f360b6d06a86 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Wed, 15 Jan 2025 13:29:25 +0000 Subject: [PATCH 24/58] There are arbitrary values that cannot work with if --- pyiron_ontology/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 538ce88..bf9b0ae 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -58,7 +58,7 @@ def get_triples(data, EX): graph.add((label, RDFS.label, Literal(full_key))) if d.get("uri", None) is not None: graph.add((label, RDF.type, d["uri"])) - if d.get("value", None): + if d.get("value", None) is not None: graph.add((label, RDF.value, Literal(d["value"]))) graph.add((label, EX[io_[:-1] + "Of"], EX[data["label"]])) if d.get("units", None) is not None: From 8af01693962cd45587db0650650baadd6a967300 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Wed, 15 Jan 2025 17:15:21 +0000 Subject: [PATCH 25/58] allow triples in triple --- pyiron_ontology/parser.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index bf9b0ae..3dcbfda 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -1,5 +1,6 @@ from semantikon.converter import parse_input_args, parse_output_args from rdflib import Graph, Literal, RDF, RDFS, URIRef +from pyiron_workflow import NOT_DATA def get_source_output(var): @@ -58,7 +59,7 @@ def get_triples(data, EX): graph.add((label, RDFS.label, Literal(full_key))) if d.get("uri", None) is not None: graph.add((label, RDF.type, d["uri"])) - if d.get("value", None) is not None: + if d.get("value", NOT_DATA) is not NOT_DATA: graph.add((label, RDF.value, Literal(d["value"]))) graph.add((label, EX[io_[:-1] + "Of"], EX[data["label"]])) if d.get("units", None) is not None: @@ -71,10 +72,19 @@ def get_triples(data, EX): else: triple = [d["triple"]] for t in triple: - obj = t[1] + if len(t) == 2: + subj = label + pred = t[0] + obj = t[1] + elif len(t) == 3: + subj = t[0] + pred = t[1] + obj = t[2] + else: + raise ValueError("Triple must have 2 or 3 elements") if obj.startswith("inputs.") or obj.startswith("outputs."): obj = data["label"] + "." + obj if not isinstance(obj, URIRef): obj = EX[obj] - graph.add((label, t[0], obj)) + graph.add((subj, pred, obj)) return graph From 333191c4066ae791096888abff3bce75ccdc33bf Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 16 Jan 2025 06:18:54 +0000 Subject: [PATCH 26/58] update semantikon version --- .ci_support/environment.yml | 2 +- pyiron_ontology/parser.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 685813c..b8ae3ec 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -6,6 +6,6 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.7 +- semantikon =0.0.8 - pyiron_workflow =0.11.2 - rdflib =7.1.1 diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 3dcbfda..c91c38a 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -73,13 +73,9 @@ def get_triples(data, EX): triple = [d["triple"]] for t in triple: if len(t) == 2: - subj = label - pred = t[0] - obj = t[1] + subj, pred, obj = label, t[0], t[1] elif len(t) == 3: - subj = t[0] - pred = t[1] - obj = t[2] + subj, pred, obj = t else: raise ValueError("Triple must have 2 or 3 elements") if obj.startswith("inputs.") or obj.startswith("outputs."): From a25767c28acfb906c09bac8e4aca147eb86032a6 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 16 Jan 2025 06:26:12 +0000 Subject: [PATCH 27/58] separate out triple parser --- pyiron_ontology/parser.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index c91c38a..113b064 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -72,15 +72,19 @@ def get_triples(data, EX): else: triple = [d["triple"]] for t in triple: - if len(t) == 2: - subj, pred, obj = label, t[0], t[1] - elif len(t) == 3: - subj, pred, obj = t - else: - raise ValueError("Triple must have 2 or 3 elements") - if obj.startswith("inputs.") or obj.startswith("outputs."): - obj = data["label"] + "." + obj - if not isinstance(obj, URIRef): - obj = EX[obj] - graph.add((subj, pred, obj)) + graph.add(_parse_triple(t, EX)) return graph + + +def _parse_triple(triple, EX): + if len(triple) == 2: + subj, pred, obj = label, triple[0], triple[1] + elif len(triple) == 3: + subj, pred, obj = triple + else: + raise ValueError("Triple must have 2 or 3 elements") + if obj.startswith("inputs.") or obj.startswith("outputs."): + obj = data["label"] + "." + obj + if not isinstance(obj, URIRef): + obj = EX[obj] + return subj, pred, obj From 212f939a86e2907862923c452034cc6c963abafa Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 16 Jan 2025 06:29:12 +0000 Subject: [PATCH 28/58] bugfix and add tests --- pyiron_ontology/parser.py | 4 ++-- tests/unit/test_parser.py | 10 ++++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 113b064..7855f68 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -72,11 +72,11 @@ def get_triples(data, EX): else: triple = [d["triple"]] for t in triple: - graph.add(_parse_triple(t, EX)) + graph.add(_parse_triple(t, EX, label=label, data=data)) return graph -def _parse_triple(triple, EX): +def _parse_triple(triple, EX, label=None, data=None): if len(triple) == 2: subj, pred, obj = label, triple[0], triple[1] elif len(triple) == 3: diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 8f35b2f..62e44ce 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -5,11 +5,14 @@ from rdflib import Namespace +EX = Namespace("http://example.org/") + + @Workflow.wrap.as_function_node("speed") def calculate_speed( distance: u(float, units="meter"), time: u(float, units="second"), -) -> u(float, units="meter/second"): +) -> u(float, units="meter/second", triple=(EX.isOutputOf, "inputs.time")): return distance / time @@ -21,13 +24,16 @@ def test_parser(self): self.assertIn(label, output_dict) def test_triples(self): - EX = Namespace("http://example.org/") speed = calculate_speed() data = get_inputs_and_outputs(speed) graph = get_triples(data, EX) self.assertGreater( len(list(graph.triples((None, EX.hasUnits, EX["meter/second"])))), 0 ) + self.assertGreater( + len(list(graph.triples((None, EX.isOutputOf, EX["calculate_speed.inputs.time"])))), + 0 + ) if __name__ == "__main__": From 1fb1b0e8f2de7e95aca428fa8c273f9fb52eecd5 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 16 Jan 2025 06:30:31 +0000 Subject: [PATCH 29/58] one more test for a full triple --- tests/unit/test_parser.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 62e44ce..a033029 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -12,7 +12,14 @@ def calculate_speed( distance: u(float, units="meter"), time: u(float, units="second"), -) -> u(float, units="meter/second", triple=(EX.isOutputOf, "inputs.time")): +) -> u( + float, + units="meter/second", + triple=( + (EX.isOutputOf, "inputs.time"), + (EX.subject, EX.predicate, EX.object) + ) +): return distance / time @@ -34,6 +41,10 @@ def test_triples(self): len(list(graph.triples((None, EX.isOutputOf, EX["calculate_speed.inputs.time"])))), 0 ) + self.assertGreater( + len(list(graph.triples((EX.subject, EX.predicate, EX.object)))), + 0 + ) if __name__ == "__main__": From cd42a96eed8b5e2d4a4972fb5de7e0680b1fe647 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 16 Jan 2025 06:59:28 +0000 Subject: [PATCH 30/58] make it possible to give custom predicates --- pyiron_ontology/parser.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 7855f68..22a8079 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -46,9 +46,19 @@ def get_inputs_and_outputs(node): } -def get_triples(data, EX): +def get_triples( + data, EX, hasSourceFunction=None, comesFrom=None, hasUnits=None +): + if hasSourceFunction is None: + hasSourceFunction = EX.hasSourceFunction + if comesFrom is None: + comesFrom = EX.comesFrom + if hasUnits is None: + hasUnits = EX.hasUnits graph = Graph() - label_def_triple = (EX[data["label"]], EX.hasSourceFunction, EX[data["function"]]) + label_def_triple = ( + EX[data["label"]], hasSourceFunction, EX[data["function"]] + ) if len(list(graph.triples(label_def_triple))) > 0: return graph graph.add(label_def_triple) @@ -63,9 +73,9 @@ def get_triples(data, EX): graph.add((label, RDF.value, Literal(d["value"]))) graph.add((label, EX[io_[:-1] + "Of"], EX[data["label"]])) if d.get("units", None) is not None: - graph.add((label, EX.hasUnits, EX[d["units"]])) + graph.add((label, hasUnits, EX[d["units"]])) if d.get("connection", None) is not None: - graph.add((label, EX.comesFrom, EX[d["connection"]])) + graph.add((label, comesFrom, EX[d["connection"]])) if d.get("triple", None) is not None: if isinstance(d["triple"][0], tuple | list): triple = list(d["triple"]) From 38bb43c537cc73f1516c97df0fe6f06745f9a3a3 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 16 Jan 2025 07:01:21 +0000 Subject: [PATCH 31/58] experiment: use sameAs instead of comesFrom --- pyiron_ontology/parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 22a8079..e2b8d87 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -1,5 +1,5 @@ from semantikon.converter import parse_input_args, parse_output_args -from rdflib import Graph, Literal, RDF, RDFS, URIRef +from rdflib import Graph, Literal, RDF, RDFS, URIRef, OWL from pyiron_workflow import NOT_DATA @@ -52,7 +52,7 @@ def get_triples( if hasSourceFunction is None: hasSourceFunction = EX.hasSourceFunction if comesFrom is None: - comesFrom = EX.comesFrom + comesFrom = OWL.sameAs if hasUnits is None: hasUnits = EX.hasUnits graph = Graph() From d8f0757c51fdd87557766022c5c5a1f6a739b1eb Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 16 Jan 2025 09:49:01 +0000 Subject: [PATCH 32/58] implement inherit properties --- pyiron_ontology/parser.py | 35 +++++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index e2b8d87..e3040fd 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -47,14 +47,19 @@ def get_inputs_and_outputs(node): def get_triples( - data, EX, hasSourceFunction=None, comesFrom=None, hasUnits=None + data, + EX, + hasSourceFunction=None, + hasUnits=None, + inheritsPropertiesFrom=None, + update_query=True ): if hasSourceFunction is None: hasSourceFunction = EX.hasSourceFunction - if comesFrom is None: - comesFrom = OWL.sameAs if hasUnits is None: hasUnits = EX.hasUnits + if inheritsPropertiesFrom is None: + inheritsPropertiesFrom = EX.inheritsPropertiesFrom graph = Graph() label_def_triple = ( EX[data["label"]], hasSourceFunction, EX[data["function"]] @@ -75,7 +80,7 @@ def get_triples( if d.get("units", None) is not None: graph.add((label, hasUnits, EX[d["units"]])) if d.get("connection", None) is not None: - graph.add((label, comesFrom, EX[d["connection"]])) + graph.add((label, inheritsPropertiesFrom, EX[d["connection"]])) if d.get("triple", None) is not None: if isinstance(d["triple"][0], tuple | list): triple = list(d["triple"]) @@ -83,6 +88,8 @@ def get_triples( triple = [d["triple"]] for t in triple: graph.add(_parse_triple(t, EX, label=label, data=data)) + if update_query: + _inherit_properties(graph, EX) return graph @@ -98,3 +105,23 @@ def _parse_triple(triple, EX, label=None, data=None): if not isinstance(obj, URIRef): obj = EX[obj] return subj, pred, obj + + +def _inherit_properties(graph, NS): + update_query = ( + f"PREFIX ns: <{NS}>", + f"PREFIX rdfs: <{RDFS}>", + f"PREFIX rdf: <{RDF}>", + "", + "INSERT {", + " ?subject ?p ?o .", + "}", + "WHERE {", + " ?subject ns:inheritsPropertiesFrom ?target .", + " ?target ?p ?o .", + " FILTER(?p != ns:inheritsPropertiesFrom)", + " FILTER(?p != rdfs:label)", + " FILTER(?p != rdf:value)", + "}" + ) + graph.update("\n".join(update_query)) From 918d141a8251ef4c483138db4940267a1b3a3287 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 16 Jan 2025 14:39:15 +0000 Subject: [PATCH 33/58] make inherit properties a public function --- pyiron_ontology/parser.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index e3040fd..50eb5b7 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -89,7 +89,7 @@ def get_triples( for t in triple: graph.add(_parse_triple(t, EX, label=label, data=data)) if update_query: - _inherit_properties(graph, EX) + inherit_properties(graph, EX) return graph @@ -107,7 +107,7 @@ def _parse_triple(triple, EX, label=None, data=None): return subj, pred, obj -def _inherit_properties(graph, NS): +def inherit_properties(graph, NS): update_query = ( f"PREFIX ns: <{NS}>", f"PREFIX rdfs: <{RDFS}>", From 71eeed183f49234bb83c02c9e098a99f41a8c75b Mon Sep 17 00:00:00 2001 From: samwaseda Date: Thu, 16 Jan 2025 15:52:51 +0000 Subject: [PATCH 34/58] add restriction parser --- pyiron_ontology/parser.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 50eb5b7..dc90757 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -81,18 +81,37 @@ def get_triples( graph.add((label, hasUnits, EX[d["units"]])) if d.get("connection", None) is not None: graph.add((label, inheritsPropertiesFrom, EX[d["connection"]])) + triples = [] + if d.get("restriction", None) is not None: + triples = restriction_to_triple(d["restriction"]) if d.get("triple", None) is not None: if isinstance(d["triple"][0], tuple | list): - triple = list(d["triple"]) + triples.extend(list(d["triple"])) else: - triple = [d["triple"]] - for t in triple: + triples.extend([d["triple"]]) + if len(triples) > 0: + for t in triples: graph.add(_parse_triple(t, EX, label=label, data=data)) if update_query: inherit_properties(graph, EX) return graph +def restriction_to_triple(restriction): + triples = [] + assert isinstance(restriction, tuple) and isinstance(restriction[0], tuple) + if not isinstance(restriction[0][0], tuple): + restriction = (restriction,) + for r in restriction: + assert len(r[0]) == 2 + label = r[0][1] + "Restriction" + triples.append((label, RDF.type, OWL.Restriction)) + for rr in r: + triples.append((label, rr[0], rr[1])) + triples.append((RDF.type, label)) + return triples + + def _parse_triple(triple, EX, label=None, data=None): if len(triple) == 2: subj, pred, obj = label, triple[0], triple[1] From c18444baf4356194ca128fc6b4b2cd430e619843 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Thu, 16 Jan 2025 15:54:57 +0000 Subject: [PATCH 35/58] [dependabot skip] Update env file --- .binder/environment.yml | 2 +- docs/environment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.binder/environment.yml b/.binder/environment.yml index 94d5a02..db1f937 100644 --- a/.binder/environment.yml +++ b/.binder/environment.yml @@ -6,7 +6,7 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.7 +- semantikon =0.0.8 - pyiron_workflow =0.11.2 - rdflib =7.1.1 - pyiron_atomistics =0.6.19 diff --git a/docs/environment.yml b/docs/environment.yml index cd95950..ee5ede1 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -12,7 +12,7 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.7 +- semantikon =0.0.8 - pyiron_workflow =0.11.2 - rdflib =7.1.1 - sphinxcontrib-mermaid From bcf33dd9b9cc763bd71849aae40ecacf98dd6d91 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Fri, 17 Jan 2025 07:26:58 +0000 Subject: [PATCH 36/58] raise lower bound of semantikon --- .ci_support/lower_bound.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/lower_bound.yml b/.ci_support/lower_bound.yml index 50ed90b..36945f3 100644 --- a/.ci_support/lower_bound.yml +++ b/.ci_support/lower_bound.yml @@ -8,6 +8,6 @@ dependencies: - pint =0.23 - pyiron_atomistics =0.5.0 - pyiron-data =0.0.26 -- semantikon =0.0.6 +- semantikon =0.0.8 - pyiron_workflow =0.11.2 - rdflib =7.1.1 From eefe3fa6405465cdca939a8cd1de7cbae9c7599c Mon Sep 17 00:00:00 2001 From: samwaseda Date: Fri, 17 Jan 2025 07:27:58 +0000 Subject: [PATCH 37/58] run black --- pyiron_ontology/parser.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index dc90757..b800b97 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -52,7 +52,7 @@ def get_triples( hasSourceFunction=None, hasUnits=None, inheritsPropertiesFrom=None, - update_query=True + update_query=True, ): if hasSourceFunction is None: hasSourceFunction = EX.hasSourceFunction @@ -61,9 +61,7 @@ def get_triples( if inheritsPropertiesFrom is None: inheritsPropertiesFrom = EX.inheritsPropertiesFrom graph = Graph() - label_def_triple = ( - EX[data["label"]], hasSourceFunction, EX[data["function"]] - ) + label_def_triple = (EX[data["label"]], hasSourceFunction, EX[data["function"]]) if len(list(graph.triples(label_def_triple))) > 0: return graph graph.add(label_def_triple) @@ -141,6 +139,6 @@ def inherit_properties(graph, NS): " FILTER(?p != ns:inheritsPropertiesFrom)", " FILTER(?p != rdfs:label)", " FILTER(?p != rdf:value)", - "}" + "}", ) graph.update("\n".join(update_query)) From 43a5009fd82e025faad6d7e750702359a69c6432 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Fri, 17 Jan 2025 15:47:46 +0000 Subject: [PATCH 38/58] add reasoner --- pyiron_ontology/parser.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index b800b97..44f87bb 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -142,3 +142,29 @@ def inherit_properties(graph, NS): "}", ) graph.update("\n".join(update_query)) + + +def check_values(graph): + query = ( + "PREFIX rdf: ", + "PREFIX owl: ", + "SELECT ?subject ?property ?value", + "WHERE {", + " ?restriction a owl:Restriction ;", + " owl:onProperty ?property ;", + " owl:hasValue ?expectedValue .", + " ?subject ?property ?value .", + " FILTER NOT EXISTS {", + " ?value a ?expectedValue .", + " }", + "}", + ) + + results = graph.query("\n".join(query)) + + if len(results) > 0: + print("Graph violates OWL restrictions:") + for row in results: + print(f"Subject: {row.subject}, Property: {row.property}, Value: {row.value}") + return results + return [] From bc64153189622d4cb0013f23dcf98eb447b35bf7 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Fri, 17 Jan 2025 15:48:53 +0000 Subject: [PATCH 39/58] Replace [] by None --- pyiron_ontology/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 44f87bb..8c42d29 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -167,4 +167,4 @@ def check_values(graph): for row in results: print(f"Subject: {row.subject}, Property: {row.property}, Value: {row.value}") return results - return [] + return None From ed2d03016e90ffe0729bcdd0897126da265c99b0 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Sat, 18 Jan 2025 09:20:47 +0000 Subject: [PATCH 40/58] implement validator --- pyiron_ontology/parser.py | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 8c42d29..ff45574 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -144,27 +144,16 @@ def inherit_properties(graph, NS): graph.update("\n".join(update_query)) -def check_values(graph): - query = ( - "PREFIX rdf: ", - "PREFIX owl: ", - "SELECT ?subject ?property ?value", - "WHERE {", - " ?restriction a owl:Restriction ;", - " owl:onProperty ?property ;", - " owl:hasValue ?expectedValue .", - " ?subject ?property ?value .", - " FILTER NOT EXISTS {", - " ?value a ?expectedValue .", - " }", - "}", - ) - - results = graph.query("\n".join(query)) - - if len(results) > 0: - print("Graph violates OWL restrictions:") - for row in results: - print(f"Subject: {row.subject}, Property: {row.property}, Value: {row.value}") - return results - return None +def validate_values(graph): + missing_triples = [] + for restriction in graph.subjects(RDF.type, OWL.Restriction): + on_property = graph.value(restriction, OWL.onProperty) + some_values_from = graph.value(restriction, OWL.someValuesFrom) + if on_property and some_values_from: + for cls in graph.subjects(OWL.equivalentClass, restriction): + for instance in graph.subjects(RDF.type, cls): + if not (instance, on_property, some_values_from) in graph: + missing_triples.append( + (instance, on_property, some_values_from) + ) + return missing_triples From 20fb3a8e10c0da6570404b2ab6b9b9aea12a1867 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Sat, 18 Jan 2025 09:37:47 +0000 Subject: [PATCH 41/58] Do not inherit type --- pyiron_ontology/parser.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index ff45574..724e63d 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -139,6 +139,7 @@ def inherit_properties(graph, NS): " FILTER(?p != ns:inheritsPropertiesFrom)", " FILTER(?p != rdfs:label)", " FILTER(?p != rdf:value)", + " FILTER(?p != rdf:type)", "}", ) graph.update("\n".join(update_query)) From f4f8dd66a17694a7d4493ce963f47fa76ba1071c Mon Sep 17 00:00:00 2001 From: samwaseda Date: Sat, 18 Jan 2025 10:08:53 +0000 Subject: [PATCH 42/58] calculate number of iterations automatically --- pyiron_ontology/parser.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 724e63d..62aa77f 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -124,7 +124,7 @@ def _parse_triple(triple, EX, label=None, data=None): return subj, pred, obj -def inherit_properties(graph, NS): +def inherit_properties(graph, NS, n=None): update_query = ( f"PREFIX ns: <{NS}>", f"PREFIX rdfs: <{RDFS}>", @@ -142,7 +142,10 @@ def inherit_properties(graph, NS): " FILTER(?p != rdf:type)", "}", ) - graph.update("\n".join(update_query)) + if n is None: + n = len(list(graph.triples((None, NS.inheritsPropertiesFrom, None)))) - 1 + for _ in range(n): + graph.update("\n".join(update_query)) def validate_values(graph): From 7dbf3c231033030d603db61e31a2cf31e4af222f Mon Sep 17 00:00:00 2001 From: samwaseda Date: Sun, 19 Jan 2025 08:04:38 +0000 Subject: [PATCH 43/58] adjust line length --- tests/unit/test_parser.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index a033029..0f8a849 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -38,7 +38,13 @@ def test_triples(self): len(list(graph.triples((None, EX.hasUnits, EX["meter/second"])))), 0 ) self.assertGreater( - len(list(graph.triples((None, EX.isOutputOf, EX["calculate_speed.inputs.time"])))), + len( + list( + graph.triples( + (None, EX.isOutputOf, EX["calculate_speed.inputs.time"]) + ) + ) + ), 0 ) self.assertGreater( From 077c9804627ae15ca6e7dc3642c214eae8644c7a Mon Sep 17 00:00:00 2001 From: samwaseda Date: Sun, 19 Jan 2025 08:07:00 +0000 Subject: [PATCH 44/58] be more specific about the number of triples in tests --- tests/unit/test_parser.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 0f8a849..6ee68a8 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -37,7 +37,7 @@ def test_triples(self): self.assertGreater( len(list(graph.triples((None, EX.hasUnits, EX["meter/second"])))), 0 ) - self.assertGreater( + self.assertEqual( len( list( graph.triples( @@ -45,11 +45,11 @@ def test_triples(self): ) ) ), - 0 + 1 ) - self.assertGreater( + self.assertEqual( len(list(graph.triples((EX.subject, EX.predicate, EX.object)))), - 0 + 1 ) From a7209445b0a1f2bbb9a2859cee0b4a1b9d784b19 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Sun, 19 Jan 2025 08:26:17 +0000 Subject: [PATCH 45/58] Add tests (but not working right now) --- tests/unit/test_parser.py | 65 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 6ee68a8..702caf0 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -1,5 +1,7 @@ import unittest -from pyiron_ontology.parser import get_inputs_and_outputs, get_triples +from owlrl import DeductiveClosure, OWLRL_Semantics +from rdflib import Graph, OWL, RDF +from pyiron_ontology.parser import get_inputs_and_outputs, get_triples, inherit_properties, validate_values from pyiron_workflow import Workflow from semantikon.typing import u from rdflib import Namespace @@ -23,6 +25,48 @@ def calculate_speed( return distance / time +@Workflow.wrap.as_function_node("result") +def add(a: float, b: float) -> u(float, triple=(EX.HasOperation, EX.Addition)): + return a + b + + +@Workflow.wrap.as_function_node("result") +def multiply(a: float, b: float) -> u( + float, + triple=( + (EX.HasOperation, EX.Multiplication), + (EX.inheritsPropertiesFrom, "inputs.a") + ) +): + return a * b + + +@Workflow.wrap.as_function_node("result") +def correct_analysis( + a: u( + float, + restriction=( + (OWL.onProperty, EX.HasOperation), + (OWL.someValuesFrom, EX.Addition) + ) + ) +) -> float: + return a + + +@Workflow.wrap.as_function_node("result") +def wrong_analysis( + a: u( + float, + restriction=( + (OWL.onProperty, EX.HasOperation), + (OWL.someValuesFrom, EX.Division) + ) + ) +) -> float: + return a + + class TestParser(unittest.TestCase): def test_parser(self): c = calculate_speed() @@ -52,6 +96,25 @@ def test_triples(self): 1 ) + def test_correct_analysis(self): + def get_graph(wf): + graph = Graph() + graph.add((EX.HasOperation, RDF.type, RDF.Property)) + graph.add((EX.Addition, RDF.type, OWL.Class)) + graph.add((EX.Multiplication, RDF.type, OWL.Class)) + for key, value in wf.children.items(): + data = get_inputs_and_outputs(value) + graph += get_triples(data, EX) + inherit_properties(graph, EX) + DeductiveClosure(OWLRL_Semantics).expand(graph) + return graph + wf = Workflow("correct_analysis") + wf.addition = add(a=1., b=2.) + wf.multiply = multiply(a=wf.addition, b=3.) + wf.analysis = correct_analysis(a=wf.multiply) + graph = get_graph(wf) + self.assertEqual(len(validate_values(graph)), 0) + if __name__ == "__main__": unittest.main() From f34f52da0a37ddbba937646b36de580dcb8abd6a Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 20 Jan 2025 06:07:29 +0000 Subject: [PATCH 46/58] increase number of inheritances --- pyiron_ontology/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index 62aa77f..c421e08 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -143,7 +143,7 @@ def inherit_properties(graph, NS, n=None): "}", ) if n is None: - n = len(list(graph.triples((None, NS.inheritsPropertiesFrom, None)))) - 1 + n = len(list(graph.triples((None, NS.inheritsPropertiesFrom, None)))) for _ in range(n): graph.update("\n".join(update_query)) From 535aac1b9e24edddb15144a073f8e1ee1971c54e Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 20 Jan 2025 06:08:10 +0000 Subject: [PATCH 47/58] Add wrong analysis --- tests/unit/test_parser.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 702caf0..37c8b48 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -114,6 +114,12 @@ def get_graph(wf): wf.analysis = correct_analysis(a=wf.multiply) graph = get_graph(wf) self.assertEqual(len(validate_values(graph)), 0) + wf = Workflow("wrong_analysis") + wf.addition = add(a=1., b=2.) + wf.multiply = multiply(a=wf.addition, b=3.) + wf.analysis = wrong_analysis(a=wf.multiply) + graph = get_graph(wf) + self.assertEqual(len(validate_values(graph)), 1) if __name__ == "__main__": From 3cd1f78f0b7bf72874f8c3a3057a63a42951580e Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 20 Jan 2025 06:21:06 +0000 Subject: [PATCH 48/58] include owlrl in the environment --- .ci_support/environment.yml | 1 + .ci_support/lower_bound.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index b8ae3ec..53340ff 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -9,3 +9,4 @@ dependencies: - semantikon =0.0.8 - pyiron_workflow =0.11.2 - rdflib =7.1.1 +- owlrl =7.1.2 diff --git a/.ci_support/lower_bound.yml b/.ci_support/lower_bound.yml index 36945f3..f8f22a6 100644 --- a/.ci_support/lower_bound.yml +++ b/.ci_support/lower_bound.yml @@ -11,3 +11,4 @@ dependencies: - semantikon =0.0.8 - pyiron_workflow =0.11.2 - rdflib =7.1.1 +- owlrl =7.1.2 From 73a27412c366eee41d766dd364d5fb2441871b31 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Mon, 20 Jan 2025 06:22:06 +0000 Subject: [PATCH 49/58] [dependabot skip] Update env file --- .binder/environment.yml | 1 + docs/environment.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.binder/environment.yml b/.binder/environment.yml index db1f937..d1d3efc 100644 --- a/.binder/environment.yml +++ b/.binder/environment.yml @@ -9,6 +9,7 @@ dependencies: - semantikon =0.0.8 - pyiron_workflow =0.11.2 - rdflib =7.1.1 +- owlrl =7.1.2 - pyiron_atomistics =0.6.19 - pyiron-data =0.0.30 - lammps =2024.02.07=*_openmpi_* diff --git a/docs/environment.yml b/docs/environment.yml index ee5ede1..5298825 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -15,4 +15,5 @@ dependencies: - semantikon =0.0.8 - pyiron_workflow =0.11.2 - rdflib =7.1.1 +- owlrl =7.1.2 - sphinxcontrib-mermaid From 4dfe11207f84701ae701a96a0f68d79822dbffa4 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 20 Jan 2025 06:29:07 +0000 Subject: [PATCH 50/58] change lower bounds --- .ci_support/lower_bound.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci_support/lower_bound.yml b/.ci_support/lower_bound.yml index f8f22a6..5ee783f 100644 --- a/.ci_support/lower_bound.yml +++ b/.ci_support/lower_bound.yml @@ -4,9 +4,9 @@ dependencies: - numpy =1.26.3 - openjdk - owlready2 =0.46 -- pandas =2.1.4 +- pandas =2.2.0 - pint =0.23 -- pyiron_atomistics =0.5.0 +- pyiron_atomistics =0.6.0 - pyiron-data =0.0.26 - semantikon =0.0.8 - pyiron_workflow =0.11.2 From 972ba6d610df20dce6b9ff0f0d12bdab6c62e7c0 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 20 Jan 2025 06:33:33 +0000 Subject: [PATCH 51/58] Another try --- .ci_support/lower_bound.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci_support/lower_bound.yml b/.ci_support/lower_bound.yml index 5ee783f..c7ad49e 100644 --- a/.ci_support/lower_bound.yml +++ b/.ci_support/lower_bound.yml @@ -6,7 +6,7 @@ dependencies: - owlready2 =0.46 - pandas =2.2.0 - pint =0.23 -- pyiron_atomistics =0.6.0 +- pyiron_atomistics =0.6.5 - pyiron-data =0.0.26 - semantikon =0.0.8 - pyiron_workflow =0.11.2 From 28c7dd4ad57be028a8812212c638d37c002a393b Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 20 Jan 2025 06:39:22 +0000 Subject: [PATCH 52/58] update pint version --- .ci_support/lower_bound.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci_support/lower_bound.yml b/.ci_support/lower_bound.yml index c7ad49e..7f46171 100644 --- a/.ci_support/lower_bound.yml +++ b/.ci_support/lower_bound.yml @@ -5,8 +5,8 @@ dependencies: - openjdk - owlready2 =0.46 - pandas =2.2.0 -- pint =0.23 -- pyiron_atomistics =0.6.5 +- pint =0.24 +- pyiron_atomistics =0.6.0 - pyiron-data =0.0.26 - semantikon =0.0.8 - pyiron_workflow =0.11.2 From 394b5531fbd25105d72c11d47972b68ee9360a1e Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 20 Jan 2025 07:13:52 +0000 Subject: [PATCH 53/58] update lower bounds --- .ci_support/lower_bound.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci_support/lower_bound.yml b/.ci_support/lower_bound.yml index 7f46171..9a2d1d6 100644 --- a/.ci_support/lower_bound.yml +++ b/.ci_support/lower_bound.yml @@ -6,9 +6,9 @@ dependencies: - owlready2 =0.46 - pandas =2.2.0 - pint =0.24 -- pyiron_atomistics =0.6.0 +- pyiron_atomistics =0.6.19 - pyiron-data =0.0.26 - semantikon =0.0.8 -- pyiron_workflow =0.11.2 +- pyiron_workflow =0.11.0 - rdflib =7.1.1 - owlrl =7.1.2 From 2224b596af370f0eccebcad121f28cf32b978b62 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Mon, 20 Jan 2025 07:59:40 +0000 Subject: [PATCH 54/58] Define each label as a named individual --- pyiron_ontology/parser.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index c421e08..fe21eb9 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -61,10 +61,11 @@ def get_triples( if inheritsPropertiesFrom is None: inheritsPropertiesFrom = EX.inheritsPropertiesFrom graph = Graph() - label_def_triple = (EX[data["label"]], hasSourceFunction, EX[data["function"]]) + label_def_triple = (EX[data["label"]], RDF.type, OWL.NamedIndividual) if len(list(graph.triples(label_def_triple))) > 0: return graph graph.add(label_def_triple) + graph.add((EX[data["label"]], hasSourceFunction, EX[data["function"]])) for io_ in ["inputs", "outputs"]: for key, d in data[io_].items(): full_key = data["label"] + f".{io_}." + key From 0b1d6e208d345a3df2e939503b2510bbf9a279e6 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Tue, 21 Jan 2025 05:58:59 +0000 Subject: [PATCH 55/58] update semantikon version --- .ci_support/environment.yml | 2 +- .ci_support/lower_bound.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 53340ff..c23037e 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -6,7 +6,7 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.8 +- semantikon =0.0.9 - pyiron_workflow =0.11.2 - rdflib =7.1.1 - owlrl =7.1.2 diff --git a/.ci_support/lower_bound.yml b/.ci_support/lower_bound.yml index 9a2d1d6..db342dd 100644 --- a/.ci_support/lower_bound.yml +++ b/.ci_support/lower_bound.yml @@ -8,7 +8,7 @@ dependencies: - pint =0.24 - pyiron_atomistics =0.6.19 - pyiron-data =0.0.26 -- semantikon =0.0.8 +- semantikon =0.0.9 - pyiron_workflow =0.11.0 - rdflib =7.1.1 - owlrl =7.1.2 From 8b145559ac3fdca72c49e80582f11ffd9dcd2731 Mon Sep 17 00:00:00 2001 From: pyiron-runner Date: Tue, 21 Jan 2025 05:59:17 +0000 Subject: [PATCH 56/58] [dependabot skip] Update env file --- .binder/environment.yml | 2 +- docs/environment.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.binder/environment.yml b/.binder/environment.yml index d1d3efc..61dc0e9 100644 --- a/.binder/environment.yml +++ b/.binder/environment.yml @@ -6,7 +6,7 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.8 +- semantikon =0.0.9 - pyiron_workflow =0.11.2 - rdflib =7.1.1 - owlrl =7.1.2 diff --git a/docs/environment.yml b/docs/environment.yml index 5298825..5a59693 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -12,7 +12,7 @@ dependencies: - owlready2 =0.47 - pandas =2.2.3 - pint =0.24.4 -- semantikon =0.0.8 +- semantikon =0.0.9 - pyiron_workflow =0.11.2 - rdflib =7.1.1 - owlrl =7.1.2 From 5e8e52fd05831e71b40895d14eb443d3640ae1b9 Mon Sep 17 00:00:00 2001 From: samwaseda Date: Tue, 21 Jan 2025 06:21:23 +0000 Subject: [PATCH 57/58] Name change in order to avoid confusion --- pyiron_ontology/parser.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/pyiron_ontology/parser.py b/pyiron_ontology/parser.py index fe21eb9..1bb54fc 100644 --- a/pyiron_ontology/parser.py +++ b/pyiron_ontology/parser.py @@ -62,6 +62,7 @@ def get_triples( inheritsPropertiesFrom = EX.inheritsPropertiesFrom graph = Graph() label_def_triple = (EX[data["label"]], RDF.type, OWL.NamedIndividual) + # Triple already exists if len(list(graph.triples(label_def_triple))) > 0: return graph graph.add(label_def_triple) @@ -80,22 +81,25 @@ def get_triples( graph.add((label, hasUnits, EX[d["units"]])) if d.get("connection", None) is not None: graph.add((label, inheritsPropertiesFrom, EX[d["connection"]])) - triples = [] - if d.get("restriction", None) is not None: - triples = restriction_to_triple(d["restriction"]) - if d.get("triple", None) is not None: - if isinstance(d["triple"][0], tuple | list): - triples.extend(list(d["triple"])) - else: - triples.extend([d["triple"]]) - if len(triples) > 0: - for t in triples: - graph.add(_parse_triple(t, EX, label=label, data=data)) + for t in _get_triples_from_restrictions(d, EX): + graph.add(_parse_triple(t, EX, label=label, data=data)) if update_query: inherit_properties(graph, EX) return graph +def _get_triples_from_restrictions(data, EX): + triples = [] + if data.get("restriction", None) is not None: + triples = restriction_to_triple(data["restriction"]) + if data.get("triple", None) is not None: + if isinstance(data["triple"][0], tuple | list): + triples.extend(list(data["triple"])) + else: + triples.extend([data["triple"]]) + return triples + + def restriction_to_triple(restriction): triples = [] assert isinstance(restriction, tuple) and isinstance(restriction[0], tuple) From 992d3e526a7a57bccd3a60f9a489fb53e882d2de Mon Sep 17 00:00:00 2001 From: samwaseda Date: Tue, 21 Jan 2025 06:23:08 +0000 Subject: [PATCH 58/58] Codacy --- tests/unit/test_parser.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_parser.py b/tests/unit/test_parser.py index 37c8b48..c8c70ff 100644 --- a/tests/unit/test_parser.py +++ b/tests/unit/test_parser.py @@ -12,8 +12,8 @@ @Workflow.wrap.as_function_node("speed") def calculate_speed( - distance: u(float, units="meter"), - time: u(float, units="second"), + distance: u(float, units="meter") = 10.0, + time: u(float, units="second") = 2.0, ) -> u( float, units="meter/second", @@ -102,7 +102,7 @@ def get_graph(wf): graph.add((EX.HasOperation, RDF.type, RDF.Property)) graph.add((EX.Addition, RDF.type, OWL.Class)) graph.add((EX.Multiplication, RDF.type, OWL.Class)) - for key, value in wf.children.items(): + for value in wf.children.values(): data = get_inputs_and_outputs(value) graph += get_triples(data, EX) inherit_properties(graph, EX)