Skip to content

Commit

Permalink
ENH: Faultroom export - add mapping of juxt.pos. to SMDA names (#724)
Browse files Browse the repository at this point in the history
  • Loading branch information
ErichSuter committed Dec 5, 2024
1 parent 2980989 commit 69f1b6f
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 5 deletions.
31 changes: 28 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,
) # Same as below, but without TYPE_CHECKING

from ._base import (
ObjectDataProvider,
Expand Down Expand Up @@ -63,14 +68,34 @@ def get_bbox(self) -> BoundingBox3D:
zmax=float(self.obj.bbox["zmax"]),
)

def get_stratigraphic_name(self, name: str) -> str:
if (
isinstance(self.dataio.config, GlobalConfiguration)
and (strat := self.dataio.config.stratigraphy)
and name in strat
):
return strat[name].name

assert False, f"Official SMDA stratigraphic name not found for {name}"
# TODO: is it OK to return None? Should be an exception?
return None

def get_spec(self) -> FaultRoomSurfaceSpecification:
"""Derive data.spec for FaultRoomSurface"""
logger.info("Get spec for FaultRoomSurface")

juxtaposition_hw = []
for juxt_element in self.obj.juxtaposition_hw:
juxtaposition_hw.append(self.get_stratigraphic_name(juxt_element))
juxtaposition_fw = []
for juxt_element in self.obj.juxtaposition_fw:
juxtaposition_fw.append(self.get_stratigraphic_name(juxt_element))

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_hw,
juxtaposition_fw=juxtaposition_fw,
properties=self.obj.properties,
name=self.obj.name,
)
84 changes: 84 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,88 @@ def fixture_regsurf():
return xtgeo.RegularSurface(ncol=12, nrow=10, xinc=20, yinc=20, values=1234.0)


@pytest.fixture(name="faultroom_object_simple", scope="module")
def fixture_faultroom_object_simple():
"""Create a simple faultroom object."""
logger.debug("Ran %s", _current_function_name())
# TODO: make a very simple test with TopWhatever?
# This is contained in edataobj1 / globalconfig1
# But it is too simple, doesn't contain any formations
# Could either ignore the simple case, or use globalconfig1 and add info
# (which is not very intuitive), or keep the things beloq
# (maybe add as a new fixture)
#
# 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 = ["Valysar", "Therys", "Volon"]
juxtaposition_fw = ["Valysar", "Therys", "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="faultroom_object", scope="module")
def fixture_faultroom_object(globalconfig2):
"""Create a faultroom object."""
logger.debug("Ran %s", _current_function_name())
# TODO NOW
# Import from global_variables.yml instead of hardcoding as below
# CFG = ut.yaml_load("../../fmuconfig/output/global_variables.yml")
cfg = deepcopy(globalconfig2)

# TODO: see https://fmu-dataio.readthedocs.io/en/latest/preparations.html
# TODO: also see pinned: test_dataio/test_units/test_dataio.py: test_alias_as_none()
# Maybe do ExportData in this manner?
# Or as shown in https://github.com/equinor/fmu-dataio/issues/724,
# first line in dataio_faultroom()

# TODO: Much of the info is not in the config, OK to make up something here?
# Or should it be in a new fixture?

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
48 changes: 46 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,48 @@ def test_objectdata_regularsurface_get_stratigraphy_element_differ(regsurf, edat
assert res.stratigraphic is True


def test_objectdata_faultroom_simple_fault_juxtaposition_get_stratigraphy_differ(
faultroom_object_simple, 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_simple, edataobj2)
assert isinstance(objdata, FaultRoomSurfaceProvider)

frss = objdata.get_spec()
assert isinstance(frss, FaultRoomSurfaceSpecification)

assert frss.juxtaposition_fw[0] == "Valysar Fm."
assert frss.juxtaposition_fw[1] == "Therys Fm."
assert frss.juxtaposition_fw[2] == "Volon Fm."
assert frss.juxtaposition_hw[0] == "Valysar Fm."
assert frss.juxtaposition_hw[1] == "Therys Fm."
assert frss.juxtaposition_hw[2] == "Volon Fm."


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 frss.juxtaposition_fw[0] == "Valysar Fm."
assert frss.juxtaposition_fw[1] == "Therys Fm."
assert frss.juxtaposition_fw[2] == "Volon Fm."
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 69f1b6f

Please sign in to comment.