Skip to content

Commit

Permalink
ENH: Faultroom export - add mapping of juxt.pos. to SMDA names (equin…
Browse files Browse the repository at this point in the history
  • Loading branch information
ErichSuter committed Dec 12, 2024
1 parent 61d17d4 commit b13c2ba
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 7 deletions.
31 changes: 31 additions & 0 deletions src/fmu/dataio/_model/global_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,37 @@ def __getitem__(self, item: str) -> StratigraphyElement:
return self.root[item]


def _get_index(self, name: str) -> int:
"""
Get the index of a stratigraphic element by name.
"""
return list(self.root.keys()).index(name)


def get_official_name(self, name: str) -> str:
"""
Get the official SMDA name of a stratigraphic element.
name: name of stratigraphic element
"""
if name in self.root:
return self.root[name].name
return ""


def get_ordered_official_names(self, names: list[str]) -> list[str]:
"""
Retrieve the official SMDA names and order them according to
the stratigraphic column.
names: names of stratigraphic elements
"""
try:
sorted_indices = sorted([self._get_index(name) for name in names])
return [self.get_official_name(list(self.root.keys())[idx])
for idx in sorted_indices]
except ValueError:
return []


class GlobalConfiguration(BaseModel):
"""
Validates and manages the global configuration for the application.
Expand Down
23 changes: 20 additions & 3 deletions src/fmu/dataio/providers/objectdata/_faultroom.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
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,
) # TODO: OK? Same as below, but without TYPE_CHECKING

from ._base import (
ObjectDataProvider,
Expand Down Expand Up @@ -66,11 +71,23 @@ def get_bbox(self) -> BoundingBox3D:
def get_spec(self) -> FaultRoomSurfaceSpecification:
"""Derive data.spec for FaultRoomSurface"""
logger.info("Get spec for FaultRoomSurface")

juxtaposition_ordered_hw = []
juxtaposition_ordered_fw = []
if (
isinstance(self.dataio.config, GlobalConfiguration)
and (strat := self.dataio.config.stratigraphy)
):
juxtaposition_ordered_hw = strat.get_ordered_official_names(
self.obj.juxtaposition_hw)
juxtaposition_ordered_fw = strat.get_ordered_official_names(
self.obj.juxtaposition_fw)

return FaultRoomSurfaceSpecification(
horizons=self.obj.horizons,
faults=self.obj.faults,
juxtaposition_hw=self.obj.juxtaposition_hw,
juxtaposition_fw=self.obj.juxtaposition_fw,
juxtaposition_hw=juxtaposition_ordered_hw,
juxtaposition_fw=juxtaposition_ordered_fw,
properties=self.obj.properties,
name=self.obj.name,
)
31 changes: 31 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import logging
import os
import shutil
from copy import deepcopy
from pathlib import Path

import numpy as np
Expand All @@ -18,6 +19,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

Expand Down Expand Up @@ -460,6 +462,35 @@ 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(globalconfig2):
"""Create a faultroom object."""
logger.debug("Ran %s", _current_function_name())
cfg = deepcopy(globalconfig2)

horizons = cfg["rms"]["horizons"]["TOP_RES"]
faults = ["F1", "F2", "F3", "F4", "F5", "F6"]
juxtaposition_hw = cfg["rms"]["zones"]["ZONE_RES"]
juxtaposition_fw = cfg["rms"]["zones"]["ZONE_RES"]
juxtaposition = {"fw": juxtaposition_fw, "hw": juxtaposition_hw}
properties = [
"Juxtaposition",
]
coordinates = [[[1.1, 1.2, 1.3], [2.1, 2.2, 2.3]]]
features = [{"geometry": {"coordinates": coordinates}}]
name = cfg["access"]["asset"]["name"]

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."""
Expand Down
4 changes: 2 additions & 2 deletions tests/test_units/test_checksum_md5.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def test_checksum_md5_for_dictionary(monkeypatch, tmp_path, globalconfig1):
assert meta["file"]["checksum_md5"] == md5sum(export_path)


def test_checksum_md5_for_faultroom(monkeypatch, tmp_path, globalconfig1, rootpath):
def test_checksum_md5_for_faultroom(monkeypatch, tmp_path, globalconfig2, rootpath):
"""
Test that the MD5 hash in the metadata is equal to one computed for
the exported file for a FaultRoomSurface
Expand All @@ -194,7 +194,7 @@ def test_checksum_md5_for_faultroom(monkeypatch, tmp_path, globalconfig1, rootpa

export_path = Path(
ExportData(
config=globalconfig1,
config=globalconfig2,
content="depth",
name="myname",
).export(fault_room_surface)
Expand Down
62 changes: 62 additions & 0 deletions tests/test_units/test_global_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,65 @@ def test_access_classification_logic():
"ssdl": {"rep_include": False},
}
)


def test_stratigraphy(edataobj2):
"""Test the stratigraphy."""

strat = edataobj2.config.stratigraphy

###### Test get index ######

# Correct name
assert strat._get_index("Valysar") == 9

# Correct name
assert strat._get_index("Therys") == 10

# Incorrect name
with pytest.raises(ValueError):
strat._get_index("Garn")

# Empty name
with pytest.raises(ValueError):
strat._get_index("")


###### Test get official name ######

# Correct name
assert "Valysar Fm.".__eq__(strat.get_official_name("Valysar"))

# Incorrect name
assert "".__eq__(strat.get_official_name("Ile"))

# Empty name
assert "".__eq__(strat.get_official_name(""))


###### Test stratigraphic ordering ######

# Correct order
assert strat.get_ordered_official_names(["Valysar", "Therys", "Volon"]) == [
"Valysar Fm.",
"Therys Fm.",
"Volon Fm.",
]

# Incorrect order
assert strat.get_ordered_official_names(["Therys", "Volon", "Valysar"]) == [
"Valysar Fm.",
"Therys Fm.",
"Volon Fm.",
]

# Single element
assert strat.get_ordered_official_names(["Volon"]) == [
"Volon Fm.",
]

# Stratigraphic element not found
assert strat.get_ordered_official_names(["Valysar", "Ile"]) == []

# Empty list
assert strat.get_ordered_official_names([]) == []
29 changes: 27 additions & 2 deletions tests/test_units/test_objectdataprovider_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import fmu.dataio as dataio
from fmu.dataio._definitions import ConfigurationError, ValidFormats
from fmu.dataio._model.specification import FaultRoomSurfaceSpecification
from fmu.dataio.providers.objectdata._faultroom import FaultRoomSurfaceProvider
from fmu.dataio.providers.objectdata._provider import (
objectdata_provider_factory,
)
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -45,6 +47,29 @@ def test_objectdata_regularsurface_get_stratigraphy_element_differ(regsurf, edat
assert res.stratigraphic is True


def test_objectdata_faultroom_fault_juxtaposition_get_stratigraphy_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 len(frss.juxtaposition_fw) == 3
assert frss.juxtaposition_fw[0] == "Valysar Fm."
assert frss.juxtaposition_fw[1] == "Therys Fm."
assert frss.juxtaposition_fw[2] == "Volon Fm."
assert len(frss.juxtaposition_hw) == 3
assert frss.juxtaposition_hw[0] == "Valysar Fm."
assert frss.juxtaposition_hw[1] == "Therys Fm."
assert frss.juxtaposition_hw[2] == "Volon Fm."


def test_objectdata_regularsurface_validate_extension(regsurf, edataobj1):
"""Test a valid extension for RegularSurface object."""

Expand Down

0 comments on commit b13c2ba

Please sign in to comment.