From bd82f043ea687ce7dec16ac5f5b211d00308d237 Mon Sep 17 00:00:00 2001 From: Erich Suter Date: Wed, 27 Nov 2024 17:25:55 +0100 Subject: [PATCH] ENH: Faultroom export - add mapping of juxt.pos. to SMDA names (#724) --- .../dataio/providers/objectdata/_faultroom.py | 46 +++++++++++++++---- tests/conftest.py | 42 +++++++++++++++++ .../test_objectdataprovider_class.py | 32 ++++++++++++- 3 files changed, 110 insertions(+), 10 deletions(-) diff --git a/src/fmu/dataio/providers/objectdata/_faultroom.py b/src/fmu/dataio/providers/objectdata/_faultroom.py index 5d9381383..da9882f04 100644 --- a/src/fmu/dataio/providers/objectdata/_faultroom.py +++ b/src/fmu/dataio/providers/objectdata/_faultroom.py @@ -7,8 +7,9 @@ from fmu.dataio._logging import null_logger from fmu.dataio._model.data import BoundingBox3D from fmu.dataio._model.enums import FMUClass, Layout +from fmu.dataio._model.global_configuration import GlobalConfiguration # TODO: OK to import? from fmu.dataio._model.specification import FaultRoomSurfaceSpecification -from fmu.dataio.readers import FaultRoomSurface +from fmu.dataio.readers import FaultRoomSurface # Same as below, but without TYPE_CHECKING from ._base import ( ObjectDataProvider, @@ -63,14 +64,43 @@ def get_bbox(self) -> BoundingBox3D: zmax=float(self.obj.bbox["zmax"]), ) + # TODO: to be renamed + def ecs_get_stratigraphic_name(self, name: str) -> str: + # @ecs: see _base.py:183 + + if ( + isinstance(self.dataio.config, GlobalConfiguration) + and (strat := self.dataio.config.stratigraphy) + # and (name := self.obj.name) + # TODO: self.obj.name is a combo of horizon names, not a single name. + # Should it be changed? Or make a new variable? + and name in strat + ): + return strat[name].name + + # TODO: "strat" contains no aliases (comes from edataobj2). Should be added? + # return ["Therys Fm.", "Valysar Fm.", "Volon Fm."] + assert False, f"Stratigraphic name not found for {name}" + return None + + def get_spec(self) -> FaultRoomSurfaceSpecification: """Derive data.spec for FaultRoomSurface""" logger.info("Get spec for FaultRoomSurface") - return FaultRoomSurfaceSpecification( - horizons=self.obj.horizons, - faults=self.obj.faults, - juxtaposition_hw=self.obj.juxtaposition_hw, - juxtaposition_fw=self.obj.juxtaposition_fw, - properties=self.obj.properties, - name=self.obj.name, + + juxtaposition_hw = [] + for strat_juxt_element in self.obj.juxtaposition_hw: + juxtaposition_hw.append(self.ecs_get_stratigraphic_name(strat_juxt_element)) + juxtaposition_fw = [] + for strat_juxt_element in self.obj.juxtaposition_fw: + juxtaposition_fw.append(self.ecs_get_stratigraphic_name(strat_juxt_element)) + + frss = FaultRoomSurfaceSpecification( + horizons = self.obj.horizons, + faults = self.obj.faults, + juxtaposition_hw = juxtaposition_hw, + juxtaposition_fw = juxtaposition_fw, + properties = self.obj.properties, + name = self.obj.name, ) + return frss diff --git a/tests/conftest.py b/tests/conftest.py index 27e1b9ea7..75e672ba8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -18,6 +18,7 @@ from fmu.dataio._model import Root, fields, global_configuration from fmu.dataio.dataio import ExportData, read_metadata from fmu.dataio.providers._fmu import FmuEnv +from fmu.dataio.readers import FaultRoomSurface from .utils import _get_nested_pydantic_models, _metadata_examples @@ -460,6 +461,47 @@ def fixture_regsurf(): return xtgeo.RegularSurface(ncol=12, nrow=10, xinc=20, yinc=20, values=1234.0) +@pytest.fixture(name="faultroom_object", scope="module") +def fixture_faultroom_object(): + """Create a faultroom object.""" + logger.debug("Ran %s", _current_function_name()) + # TODO: make complete object? + # TODO: I've made this object by copying from + # 'tests/data/drogon/rms/output/faultroom/ex_faultroom_1.3.1.json' + # Is there a better way to do this? + # + # Other examples + # From tests/data/drogon/rms/output/faultroom/ex_faultroom_1.3.1.json + # fmu-dataio/examples/s/d/nn/xcase/realization-0/iter-0/ + # fmuconfig/output/global_variables.yml + horizons = ["TopVolantis", "TopTherys", "TopVolon", "BaseVolon"] + faults = ["F1", "F2", "F3", "F4", "F5", "F6"] + juxtaposition_hw = ["Therys", "Valysar", "Volon"] + juxtaposition_fw = ["Therys", "Valysar", "Volon"] + juxtaposition = {"fw": juxtaposition_fw, "hw": juxtaposition_hw} + properties = \ + ["Juxtaposition", "displacement_avg", + "permeability_avg", "transmissibility_avg"] + coordinates = [[[1.1, 1.2, 1.3], [2.1, 2.2, 2.3]]] + features = [ + {"geometry": { + "coordinates": coordinates} + } + ] + name = "Drogon" + + faultroom_data = {"horizons": horizons, + "faults": {"default": faults}, + "juxtaposition": juxtaposition, + "properties": properties, + "name": name} + + return FaultRoomSurface({ + "metadata": faultroom_data, + "features": features + }) + + @pytest.fixture(name="polygons", scope="module") def fixture_polygons(): """Create an xtgeo polygons.""" diff --git a/tests/test_units/test_objectdataprovider_class.py b/tests/test_units/test_objectdataprovider_class.py index cbfd5a1a9..e4a2ba9e2 100644 --- a/tests/test_units/test_objectdataprovider_class.py +++ b/tests/test_units/test_objectdataprovider_class.py @@ -12,6 +12,8 @@ objectdata_provider_factory, ) from fmu.dataio.providers.objectdata._xtgeo import RegularSurfaceDataProvider +from fmu.dataio.providers.objectdata._faultroom import FaultRoomSurfaceProvider +from fmu.dataio._model.specification import FaultRoomSurfaceSpecification from ..conftest import remove_ert_env, set_ert_env_prehook from ..utils import inside_rms @@ -23,7 +25,7 @@ def test_objectdata_regularsurface_derive_named_stratigraphy(regsurf, edataobj1): """Get name and some stratigaphic keys for a valid RegularSurface object .""" - # mimic the stripped parts of configuations for testing here + # mimic the stripped parts of configurations for testing here objdata = objectdata_provider_factory(regsurf, edataobj1) res = objdata._get_stratigraphy_element() @@ -35,7 +37,7 @@ def test_objectdata_regularsurface_derive_named_stratigraphy(regsurf, edataobj1) def test_objectdata_regularsurface_get_stratigraphy_element_differ(regsurf, edataobj2): """Get name and some stratigaphic keys for a valid RegularSurface object .""" - # mimic the stripped parts of configuations for testing here + # mimic the stripped parts of configurations for testing here objdata = objectdata_provider_factory(regsurf, edataobj2) res = objdata._get_stratigraphy_element() @@ -45,6 +47,32 @@ def test_objectdata_regularsurface_get_stratigraphy_element_differ(regsurf, edat assert res.stratigraphic is True +def test_objectdata_faultroom_fault_juxtaposition_get_stratigraphy_elements_differ( + faultroom_object, edataobj2): + """ + Fault juxtaposition is a list of formations on the footwall and hangingwall sides. + Ensure that each name is converted to the official SMDA names. + """ + objdata = objectdata_provider_factory(faultroom_object, edataobj2) + assert isinstance(objdata, FaultRoomSurfaceProvider) + + frss = objdata.get_spec() + assert isinstance(frss, FaultRoomSurfaceSpecification) + + assert frss.juxtaposition_fw[0] == "Therys Fm." + assert frss.juxtaposition_fw[1] == "Valysar Fm." + assert frss.juxtaposition_fw[2] == "Volon Fm." + assert frss.juxtaposition_hw[0] == "Therys Fm." + assert frss.juxtaposition_hw[1] == "Valysar Fm." + assert frss.juxtaposition_hw[2] == "Volon Fm." + + # res = objdata._get_stratigraphy_element() + + # assert res.name == "VOLANTIS GP. Top" + # assert "TopVolantis" in res.alias + # assert res.stratigraphic is True + + def test_objectdata_regularsurface_validate_extension(regsurf, edataobj1): """Test a valid extension for RegularSurface object."""