From b2ee08a0404fef828552fd823d8310de478d91a7 Mon Sep 17 00:00:00 2001 From: francescalb Date: Tue, 20 Jun 2023 11:18:23 +0200 Subject: [PATCH 1/7] Updated example for documentation --- examples/ontology-from-excel/README.md | 24 ++++++++++++++++++ ...ke_microstructure_onto.py => make_onto.py} | 10 ++++++-- .../tool/imported_onto/catalog-v001.xml | 7 +++++ .../tool/imported_onto/ontology.ttl | 18 +++++++++++++ .../tool/imported_onto/subontology.ttl | 21 +++++++++++++++ .../tool/microstructure.xlsx | Bin 39192 -> 0 bytes mkdocs.yml | 1 + 7 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 examples/ontology-from-excel/README.md rename examples/ontology-from-excel/{make_microstructure_onto.py => make_onto.py} (54%) create mode 100644 examples/ontology-from-excel/tool/imported_onto/catalog-v001.xml create mode 100644 examples/ontology-from-excel/tool/imported_onto/ontology.ttl create mode 100644 examples/ontology-from-excel/tool/imported_onto/subontology.ttl delete mode 100755 examples/ontology-from-excel/tool/microstructure.xlsx diff --git a/examples/ontology-from-excel/README.md b/examples/ontology-from-excel/README.md new file mode 100644 index 000000000..e6cefe883 --- /dev/null +++ b/examples/ontology-from-excel/README.md @@ -0,0 +1,24 @@ +# Generate an ontology from excel + +This directory contains an example xlsx-file for how to document entities (classes, object properties, annotation properties and data properties) in an Excel workbook. +This workbook can then be used to generate a new ontology or update an already existing ontology with new entities (existing entities are not updated). + +Please refer to the (documentation)[https://emmo-repo.github.io/EMMOntoPy/latest/api_reference/ontopy/excelparser/] for full explanation of capabilities. + +The file onto.xlsx contains examples on how to do things correctly as well as incorrectly. +The tool will by default exit without generating the ontology if it detects concepts defined incorrectly. +However, if th argument force is set to True, it will skip concepts that are erroneously defined +and generate the ontology with what is availble. + +To run the tool directly +```console +excel2onto onto.xlsx # This will fail +excel2onto --force onto.xlsx +``` +We suggest developing your excelsheet without fails as once it starts getting big it is difficult to see what is wrong or correct. + +It is also possible to generate the ontology in python. +Look at the script make_onto.py for an example. + +That should be it. +Good luck! diff --git a/examples/ontology-from-excel/make_microstructure_onto.py b/examples/ontology-from-excel/make_onto.py similarity index 54% rename from examples/ontology-from-excel/make_microstructure_onto.py rename to examples/ontology-from-excel/make_onto.py index 9e29fe073..0c644424c 100755 --- a/examples/ontology-from-excel/make_microstructure_onto.py +++ b/examples/ontology-from-excel/make_onto.py @@ -9,8 +9,14 @@ thisdir = Path(__file__).resolve().parent ontology, catalog, errdict = create_ontology_from_excel( - thisdir / "tool/microstructure.xlsx" + thisdir / "tool/onto.xlsx", + force=True, # Note will force generation of the ontology. ) -ontology.save("microstructure_ontology.ttl", format="turtle", overwrite=True) + +# Save the ontology and write out the catalog +ontology.save("onto.ttl", format="turtle", overwrite=True) write_catalog(catalog) + +# Look at the error dictionary +print(errdict.keys()) diff --git a/examples/ontology-from-excel/tool/imported_onto/catalog-v001.xml b/examples/ontology-from-excel/tool/imported_onto/catalog-v001.xml new file mode 100644 index 000000000..f97363ba2 --- /dev/null +++ b/examples/ontology-from-excel/tool/imported_onto/catalog-v001.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/examples/ontology-from-excel/tool/imported_onto/ontology.ttl b/examples/ontology-from-excel/tool/imported_onto/ontology.ttl new file mode 100644 index 000000000..1f16f8bf7 --- /dev/null +++ b/examples/ontology-from-excel/tool/imported_onto/ontology.ttl @@ -0,0 +1,18 @@ +@prefix : . +@prefix owl: . +@prefix rdf: . +@prefix xml: . +@prefix xsd: . +@prefix rdfs: . +@prefix skos: . +@base . + + rdf:type owl:Ontology ; + owl:versionIRI ; + owl:imports ; + owl:versionInfo "0.1.0" . + + +:testclass rdf:type owl:Class ; + rdfs:subClassOf owl:Thing ; + skos:prefLabel "TestClass"@en . diff --git a/examples/ontology-from-excel/tool/imported_onto/subontology.ttl b/examples/ontology-from-excel/tool/imported_onto/subontology.ttl new file mode 100644 index 000000000..023a198d3 --- /dev/null +++ b/examples/ontology-from-excel/tool/imported_onto/subontology.ttl @@ -0,0 +1,21 @@ +@prefix : . +@prefix owl: . +@prefix rdf: . +@prefix xml: . +@prefix xsd: . +@prefix rdfs: . +@prefix skos: . +@base . + + rdf:type owl:Ontology ; + owl:versionIRI . + + +# Annotations +skos:prefLabel rdf:type owl:AnnotationProperty . +skos:altLabel rdf:type owl:AnnotationProperty . + + +:testclass2 rdf:type owl:Class ; + rdfs:subClassOf owl:Thing ; + skos:prefLabel "TestClass2"@en . diff --git a/examples/ontology-from-excel/tool/microstructure.xlsx b/examples/ontology-from-excel/tool/microstructure.xlsx deleted file mode 100755 index 0e786cb02dd899191a367af2113a9f1bd76060a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39192 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 diff --git a/mkdocs.yml b/mkdocs.yml index 93a8beb1d..e056c1245 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -90,6 +90,7 @@ nav: - Examples: - EMMOdoc: examples/emmodoc/README.md - Jupyter visualization: examples/jupyter-visualization/README.md + - Ontology generation from Excel: examples/ - ... | developers/** - Changelog: CHANGELOG.md - ... | api_reference/** From 741b91d9b82127c66b395da8bb16038c25de9d0a Mon Sep 17 00:00:00 2001 From: francescalb Date: Tue, 20 Jun 2023 11:19:31 +0200 Subject: [PATCH 2/7] Updated index in mkdocs for excel2ontoexample --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index e056c1245..58e2dc826 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -90,7 +90,7 @@ nav: - Examples: - EMMOdoc: examples/emmodoc/README.md - Jupyter visualization: examples/jupyter-visualization/README.md - - Ontology generation from Excel: examples/ + - Ontology generation from Excel: examples/ontology-from-excel/README.md - ... | developers/** - Changelog: CHANGELOG.md - ... | api_reference/** From ce54fe6fea7b598ab52bff93284fb806e583e488 Mon Sep 17 00:00:00 2001 From: francescalb Date: Tue, 20 Jun 2023 12:24:42 +0200 Subject: [PATCH 3/7] typo --- examples/ontology-from-excel/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ontology-from-excel/README.md b/examples/ontology-from-excel/README.md index e6cefe883..77688b23e 100644 --- a/examples/ontology-from-excel/README.md +++ b/examples/ontology-from-excel/README.md @@ -1,13 +1,13 @@ # Generate an ontology from excel -This directory contains an example xlsx-file for how to document entities (classes, object properties, annotation properties and data properties) in an Excel workbook. +This directory contains an example xlsx-file for how to document ontology entities (classes, object properties, annotation properties and data properties) in an Excel workbook. This workbook can then be used to generate a new ontology or update an already existing ontology with new entities (existing entities are not updated). Please refer to the (documentation)[https://emmo-repo.github.io/EMMOntoPy/latest/api_reference/ontopy/excelparser/] for full explanation of capabilities. The file onto.xlsx contains examples on how to do things correctly as well as incorrectly. The tool will by default exit without generating the ontology if it detects concepts defined incorrectly. -However, if th argument force is set to True, it will skip concepts that are erroneously defined +However, if the argument force is set to True, it will skip concepts that are erroneously defined and generate the ontology with what is availble. To run the tool directly From 53dd9af0dfe7e4eab5dda716f819932596221ace Mon Sep 17 00:00:00 2001 From: francescalb Date: Wed, 21 Jun 2023 08:37:42 +0200 Subject: [PATCH 4/7] If excel file contains relative paths perform command in same folder as excelfile --- examples/ontology-from-excel/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/ontology-from-excel/README.md b/examples/ontology-from-excel/README.md index 77688b23e..385a46352 100644 --- a/examples/ontology-from-excel/README.md +++ b/examples/ontology-from-excel/README.md @@ -12,6 +12,7 @@ and generate the ontology with what is availble. To run the tool directly ```console +cd tool # Since the excel file provides a relative path to an imported ontology excel2onto onto.xlsx # This will fail excel2onto --force onto.xlsx ``` From 7de376d3e7d1e984da335bed5e3628291768d361 Mon Sep 17 00:00:00 2001 From: francescalb Date: Wed, 21 Jun 2023 10:21:10 +0200 Subject: [PATCH 5/7] Improved error message when missing ontology to be updated --- tools/excel2onto | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/excel2onto b/tools/excel2onto index 525fae061..ac8b65129 100755 --- a/tools/excel2onto +++ b/tools/excel2onto @@ -80,12 +80,17 @@ def main(argv: list = None): except FileNotFoundError as err: if args.force: warnings.warn( - "Did not find the input ontology, " + "Did not find the output ontology to be updated, " "will fully generate a new one." ) input_ontology = None else: - raise err + raise FileNotFoundError( + "The output ontology to be updated " + "does not exist. Missing file is: ", + args.output, + err, + ) from err try: ontology, catalog, _ = create_ontology_from_excel( From b0dae68136cc7c0dae4e93e49157403c8f5efa22 Mon Sep 17 00:00:00 2001 From: francescalb Date: Wed, 21 Jun 2023 12:40:53 +0200 Subject: [PATCH 6/7] Added test --- tests/tools/test_excel2onto.py | 7 +++++++ tools/excel2onto | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/tools/test_excel2onto.py b/tests/tools/test_excel2onto.py index cd81bf325..3a047a75a 100644 --- a/tests/tools/test_excel2onto.py +++ b/tests/tools/test_excel2onto.py @@ -55,3 +55,10 @@ def test_run(get_tool: "Callable[[str], ModuleType]", tmpdir: "Path") -> None: str(test_file), ] ) + + # Test Error raised if ontology to be updated does not exist + with pytest.raises( + FileNotFoundError, + match="The output ontology to be updated does not exist", + ): + excel2onto.main([f"--output=onto_not_created.ttl", str(test_file)]) diff --git a/tools/excel2onto b/tools/excel2onto index ac8b65129..8b144d1a1 100755 --- a/tools/excel2onto +++ b/tools/excel2onto @@ -89,7 +89,6 @@ def main(argv: list = None): "The output ontology to be updated " "does not exist. Missing file is: ", args.output, - err, ) from err try: From bf04f7579e66e17497b209d3542b6d5c11ac7fac Mon Sep 17 00:00:00 2001 From: "Francesca L. Bleken" <48128015+francescalb@users.noreply.github.com> Date: Wed, 21 Jun 2023 21:33:27 +0200 Subject: [PATCH 7/7] Update examples/ontology-from-excel/README.md Co-authored-by: Jesper Friis --- examples/ontology-from-excel/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ontology-from-excel/README.md b/examples/ontology-from-excel/README.md index 385a46352..564100cb9 100644 --- a/examples/ontology-from-excel/README.md +++ b/examples/ontology-from-excel/README.md @@ -5,7 +5,7 @@ This workbook can then be used to generate a new ontology or update an already e Please refer to the (documentation)[https://emmo-repo.github.io/EMMOntoPy/latest/api_reference/ontopy/excelparser/] for full explanation of capabilities. -The file onto.xlsx contains examples on how to do things correctly as well as incorrectly. +The file `tool/onto.xlsx` contains examples on how to do things correctly as well as incorrectly. The tool will by default exit without generating the ontology if it detects concepts defined incorrectly. However, if the argument force is set to True, it will skip concepts that are erroneously defined and generate the ontology with what is availble.