From 8df122fe11d7ccded894e2de9c07ee9681950b0d Mon Sep 17 00:00:00 2001 From: Jesper Friis Date: Mon, 24 Jun 2024 15:12:42 +0200 Subject: [PATCH 1/6] Made label optional. Added unused metadata field. --- oteapi_dlite/strategies/parse.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/oteapi_dlite/strategies/parse.py b/oteapi_dlite/strategies/parse.py index 96149cb8..7b02ad50 100644 --- a/oteapi_dlite/strategies/parse.py +++ b/oteapi_dlite/strategies/parse.py @@ -52,9 +52,22 @@ class DLiteParseConfig(AttrDict): ), ] = None label: Annotated[ - str, + Optional[str], Field( - description="Label of the new DLite instance in the collection.", + description=( + "Optional label of the new DLite instance in the collection." + ), + ), + ] + datamodel: Annotated[ + Optional[str], + Field( + description=( + "DLite datamodel documenting the structure of the data set. " + "Often unused, since the datamodel is implicitly defined in " + "the strategy, but for a documentation point of view this is " + "a very important field." + ), ), ] datacache_config: Annotated[ From 2551c4d43c0060dfe02790a188e5c055fbde0d99 Mon Sep 17 00:00:00 2001 From: Jesper Friis Date: Mon, 24 Jun 2024 15:23:23 +0200 Subject: [PATCH 2/6] Update oteapi_dlite/strategies/parse.py Co-authored-by: Francesca L. Bleken <48128015+francescalb@users.noreply.github.com> --- oteapi_dlite/strategies/parse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oteapi_dlite/strategies/parse.py b/oteapi_dlite/strategies/parse.py index 7b02ad50..5e32f667 100644 --- a/oteapi_dlite/strategies/parse.py +++ b/oteapi_dlite/strategies/parse.py @@ -65,7 +65,7 @@ class DLiteParseConfig(AttrDict): description=( "DLite datamodel documenting the structure of the data set. " "Often unused, since the datamodel is implicitly defined in " - "the strategy, but for a documentation point of view this is " + "the DLite driver (DLite plugin), but for a documentation point of view this is " "a very important field." ), ), From 3daaba52ad657823df32826ee06bb8ecf106c009 Mon Sep 17 00:00:00 2001 From: "Francesca L. Bleken" <48128015+francescalb@users.noreply.github.com> Date: Mon, 24 Jun 2024 16:33:23 +0200 Subject: [PATCH 3/6] Update oteapi_dlite/strategies/parse.py --- oteapi_dlite/strategies/parse.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oteapi_dlite/strategies/parse.py b/oteapi_dlite/strategies/parse.py index 5e32f667..e13243b4 100644 --- a/oteapi_dlite/strategies/parse.py +++ b/oteapi_dlite/strategies/parse.py @@ -65,8 +65,8 @@ class DLiteParseConfig(AttrDict): description=( "DLite datamodel documenting the structure of the data set. " "Often unused, since the datamodel is implicitly defined in " - "the DLite driver (DLite plugin), but for a documentation point of view this is " - "a very important field." + "the DLite driver (DLite plugin), but for a documentation " + "point of view this is a very important field." ), ), ] From 1067c68195525c0ddcd59761a2b2cc71aea55af1 Mon Sep 17 00:00:00 2001 From: "Francesca.L.Bleken@sintef.no" Date: Mon, 24 Jun 2024 16:39:32 +0200 Subject: [PATCH 4/6] Default calue added to datamodel and label whic are now optional in parse --- oteapi_dlite/strategies/parse.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/oteapi_dlite/strategies/parse.py b/oteapi_dlite/strategies/parse.py index e13243b4..58fda358 100644 --- a/oteapi_dlite/strategies/parse.py +++ b/oteapi_dlite/strategies/parse.py @@ -58,7 +58,7 @@ class DLiteParseConfig(AttrDict): "Optional label of the new DLite instance in the collection." ), ), - ] + ] = None datamodel: Annotated[ Optional[str], Field( @@ -69,7 +69,7 @@ class DLiteParseConfig(AttrDict): "point of view this is a very important field." ), ), - ] + ] = None datacache_config: Annotated[ Optional[DataCacheConfig], Field( From db8c2128d1311b29c7eee42704b54f5bb373dba1 Mon Sep 17 00:00:00 2001 From: "Francesca.L.Bleken@sintef.no" Date: Tue, 25 Jun 2024 08:50:56 +0200 Subject: [PATCH 5/6] Parse strategy: Driver is not Optional, added test, added label --- oteapi_dlite/strategies/parse.py | 7 ++- tests/entities/Molecule.yaml | 35 ++++++++++++ tests/static/molecule.json | 16 ++++++ tests/strategies/test_parse.py | 97 ++++++++++++++++++++++++++++++++ 4 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 tests/entities/Molecule.yaml create mode 100644 tests/static/molecule.json create mode 100644 tests/strategies/test_parse.py diff --git a/oteapi_dlite/strategies/parse.py b/oteapi_dlite/strategies/parse.py index 58fda358..01a65d77 100644 --- a/oteapi_dlite/strategies/parse.py +++ b/oteapi_dlite/strategies/parse.py @@ -21,11 +21,11 @@ class DLiteParseConfig(AttrDict): """Configuration for generic DLite parser.""" driver: Annotated[ - Optional[str], + str, Field( description='Name of DLite driver (ex: "json").', ), - ] = None + ] location: Annotated[ Optional[str], Field( @@ -167,7 +167,8 @@ def get( # Insert inst into collection coll = get_collection(session) - coll.add(config.label, inst) + label = config.label if config.label else inst.uuid + coll.add(label, inst) # __TODO__ # See diff --git a/tests/entities/Molecule.yaml b/tests/entities/Molecule.yaml new file mode 100644 index 00000000..b4b75ccf --- /dev/null +++ b/tests/entities/Molecule.yaml @@ -0,0 +1,35 @@ +da31ff66-98af-590c-855d-386c63617755: + da31ff66-98af-590c-855d-386c63617755: + uuid: da31ff66-98af-590c-855d-386c63617755 + uri: http://onto-ns.com/meta/0.1/Molecule + meta: http://onto-ns.com/meta/0.3/EntitySchema + description: A minimal description of a molecules + dimensions: + natoms: Number of atoms + ncoords: Number coordinates. Always 3 + properties: + name: + type: string + description: Name of the molecule. + positions: + type: float64 + shape: + - natoms + - ncoords + unit: "\xC5ngstr\xF6m" + description: Atomic positions in Cartesian coordinates. + symbols: + type: string + shape: + - natoms + description: Chemical symbols. + masses: + type: float64 + shape: + - natoms + unit: u + description: Atomic masses. + groundstate_energy: + type: float64 + unit: eV + description: Molecule ground state energy. diff --git a/tests/static/molecule.json b/tests/static/molecule.json new file mode 100644 index 00000000..a515e078 --- /dev/null +++ b/tests/static/molecule.json @@ -0,0 +1,16 @@ +{ + "b8906302-5cd9-5e34-9fec-9d6101e52554": { + "meta": "http://onto-ns.com/meta/0.1/Molecule", + "dimensions": { + "natoms": 2, + "ncoords": 3 + }, + "properties": { + "name": "H2", + "positions": [[-1.64097, 1.37077, 0], [-1.03814, 1.74207, 0]], + "symbols": ["H", "H"], + "masses": [1.008, 1.008], + "groundstate_energy": 1.34613 + } + } +} diff --git a/tests/strategies/test_parse.py b/tests/strategies/test_parse.py new file mode 100644 index 00000000..62fbe33a --- /dev/null +++ b/tests/strategies/test_parse.py @@ -0,0 +1,97 @@ +"""Test the image formats in the image parse strategy.""" + +# pylint: disable=too-many-locals +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from pathlib import Path + from typing import Optional + + from oteapi.interfaces import IParseStrategy + + from oteapi_dlite.models import DLiteSessionUpdate + + +def test_parse_no_options( + static_files: "Path", +) -> None: + """Test the dlite-parse strategy.""" + + import dlite + from oteapi.datacache import DataCache + + from oteapi_dlite.strategies.parse import DLiteParseStrategy + + sample_file = static_files / "molecule.json" + + cache = DataCache() + + orig_key = cache.add(sample_file.read_bytes()) + config = { + "downloadUrl": sample_file.as_uri(), + "mediaType": "image/vnd.dlite-parse", + "configuration": { + "driver": "json", + }, + } + coll = dlite.Collection() + session = { + "collection_id": coll.uuid, + "key": orig_key, + } + cache.add(coll.asjson(), key=coll.uuid) + parser: "IParseStrategy" = DLiteParseStrategy(config) + output: "DLiteSessionUpdate" = parser.get(session) + assert "collection_id" in output + assert output.collection_id == coll.uuid + + # How to reach the instance if we do not have a label? + # coll2: dlite.Collection = dlite.get_instance(session["collection_id"]) + # inst: dlite.Instance = coll2.get("instance") + # assert ... + + +def test_parse_label( + static_files: "Path", +) -> None: + """Test the dlite-parse strategy.""" + + import dlite + from oteapi.datacache import DataCache + + from oteapi_dlite.strategies.parse import DLiteParseStrategy + + sample_file = static_files / "molecule.json" + + cache = DataCache() + + orig_key = cache.add(sample_file.read_bytes()) + config = { + "downloadUrl": sample_file.as_uri(), + "mediaType": "image/vnd.dlite-parse", + "configuration": { + "driver": "json", + "label": "instance", + }, + } + coll = dlite.Collection() + session = { + "collection_id": coll.uuid, + "key": orig_key, + } + cache.add(coll.asjson(), key=coll.uuid) + parser: "IParseStrategy" = DLiteParseStrategy(config) + output: "DLiteSessionUpdate" = parser.get(session) + assert "collection_id" in output + assert output.collection_id == coll.uuid + + coll2: dlite.Collection = dlite.get_instance(session["collection_id"]) + inst: dlite.Instance = coll2.get("instance") + assert inst.properties.keys() == { + "name", + "positions", + "symbols", + "masses", + "groundstate_energy", + } + assert inst.properties["name"] == "H2" From d92949c2c8dc9dd4fef23253e3aafda947c294bc Mon Sep 17 00:00:00 2001 From: Jesper Friis Date: Tue, 25 Jun 2024 14:09:12 +0200 Subject: [PATCH 6/6] Updated new dlite-parse tests --- tests/entities/Molecule.yaml | 67 +++++++++++++++++----------------- tests/strategies/paths.py | 1 + tests/strategies/test_parse.py | 26 +++++++------ 3 files changed, 48 insertions(+), 46 deletions(-) diff --git a/tests/entities/Molecule.yaml b/tests/entities/Molecule.yaml index b4b75ccf..19477675 100644 --- a/tests/entities/Molecule.yaml +++ b/tests/entities/Molecule.yaml @@ -1,35 +1,34 @@ da31ff66-98af-590c-855d-386c63617755: - da31ff66-98af-590c-855d-386c63617755: - uuid: da31ff66-98af-590c-855d-386c63617755 - uri: http://onto-ns.com/meta/0.1/Molecule - meta: http://onto-ns.com/meta/0.3/EntitySchema - description: A minimal description of a molecules - dimensions: - natoms: Number of atoms - ncoords: Number coordinates. Always 3 - properties: - name: - type: string - description: Name of the molecule. - positions: - type: float64 - shape: - - natoms - - ncoords - unit: "\xC5ngstr\xF6m" - description: Atomic positions in Cartesian coordinates. - symbols: - type: string - shape: - - natoms - description: Chemical symbols. - masses: - type: float64 - shape: - - natoms - unit: u - description: Atomic masses. - groundstate_energy: - type: float64 - unit: eV - description: Molecule ground state energy. + uuid: da31ff66-98af-590c-855d-386c63617755 + uri: http://onto-ns.com/meta/0.1/Molecule + meta: http://onto-ns.com/meta/0.3/EntitySchema + description: A minimal description of a molecules + dimensions: + natoms: Number of atoms + ncoords: Number coordinates. Always 3 + properties: + name: + type: string + description: Name of the molecule. + positions: + type: float64 + shape: + - natoms + - ncoords + unit: "\xC5ngstr\xF6m" + description: Atomic positions in Cartesian coordinates. + symbols: + type: string + shape: + - natoms + description: Chemical symbols. + masses: + type: float64 + shape: + - natoms + unit: u + description: Atomic masses. + groundstate_energy: + type: float64 + unit: eV + description: Molecule ground state energy. diff --git a/tests/strategies/paths.py b/tests/strategies/paths.py index 2934e341..3086048d 100644 --- a/tests/strategies/paths.py +++ b/tests/strategies/paths.py @@ -11,6 +11,7 @@ entitydir = testdir / "entities" inputdir = testdir / "input" outputdir = testdir / "output" +staticdir = testdir / "static" # Add utils to sys path diff --git a/tests/strategies/test_parse.py b/tests/strategies/test_parse.py index 62fbe33a..42dbd4a8 100644 --- a/tests/strategies/test_parse.py +++ b/tests/strategies/test_parse.py @@ -12,17 +12,17 @@ from oteapi_dlite.models import DLiteSessionUpdate -def test_parse_no_options( - static_files: "Path", -) -> None: +# if True: +def test_parse_no_options() -> None: """Test the dlite-parse strategy.""" import dlite from oteapi.datacache import DataCache + from paths import staticdir from oteapi_dlite.strategies.parse import DLiteParseStrategy - sample_file = static_files / "molecule.json" + sample_file = staticdir / "molecule.json" cache = DataCache() @@ -45,23 +45,25 @@ def test_parse_no_options( assert "collection_id" in output assert output.collection_id == coll.uuid - # How to reach the instance if we do not have a label? - # coll2: dlite.Collection = dlite.get_instance(session["collection_id"]) - # inst: dlite.Instance = coll2.get("instance") - # assert ... + # Get all instances of given metaid (there should only be one instance) + metaid = "http://onto-ns.com/meta/0.1/Molecule" + instances = list(coll.get_instances(metaid=metaid)) + assert len(instances) == 1 + (inst,) = instances + assert inst.meta.uri == metaid -def test_parse_label( - static_files: "Path", -) -> None: +# if True: +def test_parse_label() -> None: """Test the dlite-parse strategy.""" import dlite from oteapi.datacache import DataCache + from paths import staticdir from oteapi_dlite.strategies.parse import DLiteParseStrategy - sample_file = static_files / "molecule.json" + sample_file = staticdir / "molecule.json" cache = DataCache()