Skip to content

Commit

Permalink
MAINT: Align fmu_context in schema with internal
Browse files Browse the repository at this point in the history
  • Loading branch information
tnatt committed Jun 21, 2024
1 parent 625cb95 commit 0ebdeb8
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 130 deletions.
17 changes: 10 additions & 7 deletions schema/definitions/0.8.0/schema/fmu_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -408,13 +408,7 @@
"description": "The internal FMU context in which this data object was produced",
"properties": {
"stage": {
"enum": [
"case",
"iteration",
"realization"
],
"title": "Stage",
"type": "string"
"$ref": "#/$defs/FmuContext"
}
},
"required": [
Expand Down Expand Up @@ -3251,6 +3245,15 @@
"title": "FluidContactContent",
"type": "object"
},
"FmuContext": {
"enum": [
"case",
"iteration",
"realization"
],
"title": "FmuContext",
"type": "string"
},
"Geometry": {
"properties": {
"name": {
Expand Down
32 changes: 2 additions & 30 deletions src/fmu/dataio/_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from __future__ import annotations

from enum import Enum, unique
from typing import Final, Type
from enum import Enum
from typing import Final

SCHEMA: Final = (
"https://main-fmu-schemas-prod.radix.equinor.com/schemas/0.8.0/fmu_results.json"
Expand Down Expand Up @@ -75,31 +75,3 @@ class ExportFolder(str, Enum):
"timeseries": ["DATE"], # summary
"wellpicks": ["WELL", "HORIZON"],
}


@unique
class FmuContext(str, Enum):
"""
Use a Enum class for fmu_context entries.
The different entries will impact where data is exported:
REALIZATION: To realization-N/iter_M/share
CASE: To casename/share, but will also work on project disk
ITERATION: To casename/itername/share, only applicable for aggregated data
NON_FMU: Not ran in a FMU setting, e.g. interactive RMS.
"""

REALIZATION = "realization"
CASE = "case"
ITERATION = "iteration"
NON_FMU = "non-fmu"

@classmethod
def list_valid_values(cls) -> list[str]:
return [m.value for m in cls]

@classmethod
def _missing_(cls: Type[FmuContext], value: object) -> None:
raise ValueError(
f"Invalid FmuContext {value=}. Valid entries are {cls.list_valid_values()}"
)
4 changes: 2 additions & 2 deletions src/fmu/dataio/aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from pydantic import ValidationError

from . import _utils, dataio, types
from ._definitions import FmuContext
from ._logging import null_logger
from ._metadata import generate_meta_tracklog
from .datastructure.meta.enums import FmuContext
from .providers.objectdata._provider import objectdata_provider_factory

logger: Final = null_logger(__name__)
Expand Down Expand Up @@ -230,7 +230,7 @@ def _generate_aggrd_metadata(
template["fmu"]["aggregation"]["id"] = self.aggregation_id

# fmu.context.stage should be 'iteration'
template["fmu"]["context"]["stage"] = FmuContext.ITERATION.value
template["fmu"]["context"]["stage"] = FmuContext.iteration.value

# next, the new object will trigger update of: 'file', 'data' (some fields) and
# 'tracklog'.
Expand Down
34 changes: 17 additions & 17 deletions src/fmu/dataio/dataio.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@
from warnings import warn

from . import types
from ._definitions import (
FmuContext,
ValidationError,
)
from ._definitions import ValidationError
from ._logging import null_logger
from ._metadata import generate_export_metadata
from ._utils import (
Expand All @@ -31,6 +28,7 @@
from .case import InitializeCase
from .datastructure.configuration import global_configuration
from .datastructure.meta import enums
from .datastructure.meta.enums import FmuContext
from .preprocessed import ExportPreprocessedData
from .providers._fmu import FmuProvider, get_fmu_context_from_environment

Expand Down Expand Up @@ -411,7 +409,7 @@ def __post_init__(self) -> None:

self._show_deprecations_or_notimplemented()

self._fmurun = get_fmu_context_from_environment() != FmuContext.NON_FMU
self._fmurun = get_fmu_context_from_environment() is not None

# set defaults for mutable keys
self.vertical_domain = {"depth": "msl"}
Expand Down Expand Up @@ -659,21 +657,21 @@ def _validate_and_establish_fmucontext(self) -> None:
elif not self._fmurun:
logger.warning(
"Requested fmu_context is <%s> but since this is detected as a non "
"FMU run, the actual context is force set to non-fmu",
"FMU run, the actual context is force set to None",
self.fmu_context,
)
self.fmu_context = FmuContext.NON_FMU
self.fmu_context = None

else:
self.fmu_context = FmuContext(self.fmu_context.lower())
logger.info("FMU context is %s", self.fmu_context)

if self.preprocessed and self.fmu_context == FmuContext.REALIZATION:
if self.preprocessed and self.fmu_context == FmuContext.realization:
raise ValueError(
"Can't export preprocessed data in a fmu_context='realization'."
)

if self.fmu_context != FmuContext.CASE and env_fmu_context == FmuContext.CASE:
if self.fmu_context != FmuContext.case and env_fmu_context == FmuContext.case:
warn(
"fmu_context is set to 'realization', but unable to detect "
"ERT runpath from environment variable. "
Expand Down Expand Up @@ -725,23 +723,25 @@ def _establish_rootpath(self) -> Path:
logger.debug(
"inside RMS flag is %s (actual: %s))", ExportData._inside_rms, INSIDE_RMS
)
assert isinstance(self.fmu_context, FmuContext)

if self._fmurun and (
casepath := FmuProvider(
if self._fmurun:
assert isinstance(self.fmu_context, FmuContext)
if casepath := FmuProvider(
fmu_context=self.fmu_context,
casepath_proposed=Path(self.casepath) if self.casepath else None,
).get_casepath()
):
logger.info("Run from ERT")
return casepath.absolute()
).get_casepath():
logger.info("Run from ERT")
return casepath.absolute()

if ExportData._inside_rms or INSIDE_RMS:
logger.info("Run from inside RMS")
ExportData._inside_rms = True
return self._pwd.parent.parent.absolute().resolve()

logger.info("Running outside FMU context, using pwd as roothpath")
logger.info(
"Running outside FMU context or casepath with valid case metadata "
"could not be detected, will use pwd as roothpath."
)
return self._pwd

def _get_fmu_provider(self) -> FmuProvider:
Expand Down
4 changes: 2 additions & 2 deletions src/fmu/dataio/datastructure/_internal/internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from textwrap import dedent
from typing import List, Literal, Optional, Union

from fmu.dataio._definitions import SCHEMA, SOURCE, VERSION, FmuContext
from fmu.dataio._definitions import SCHEMA, SOURCE, VERSION
from fmu.dataio.datastructure.meta import meta
from pydantic import (
AnyHttpUrl,
Expand Down Expand Up @@ -112,7 +112,7 @@ class FMUModelCase(BaseModel):


class Context(BaseModel, use_enum_values=True):
stage: FmuContext
stage: meta.enums.FmuContext


# Remove the two models below when content is required as input.
Expand Down
6 changes: 6 additions & 0 deletions src/fmu/dataio/datastructure/meta/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,9 @@ class Layout(str, Enum):
table = "table"
dictionary = "dictionary"
faultroom_triangulated = "faultroom_triangulated"


class FmuContext(str, Enum):
case = "case"
iteration = "iteration"
realization = "realization"
6 changes: 1 addition & 5 deletions src/fmu/dataio/datastructure/meta/meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,11 +338,7 @@ class Display(BaseModel):
class Context(BaseModel):
"""The internal FMU context in which this data object was produced"""

stage: Literal[
"case",
"iteration",
"realization",
]
stage: enums.FmuContext


class FMUClassMetaCase(BaseModel):
Expand Down
6 changes: 3 additions & 3 deletions src/fmu/dataio/preprocessed.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
import yaml
from pydantic import ValidationError

from ._definitions import FmuContext
from ._logging import null_logger
from ._metadata import generate_meta_tracklog
from ._utils import export_metadata_file, md5sum
from .datastructure._internal import internal
from .datastructure.meta import meta
from .datastructure.meta.enums import FmuContext
from .exceptions import InvalidMetadataError
from .providers._filedata import ShareFolder
from .providers._fmu import (
Expand Down Expand Up @@ -61,14 +61,14 @@ class ExportPreprocessedData:
_fmudata: FmuProvider | None = field(default=None)

def __post_init__(self) -> None:
if get_fmu_context_from_environment() != FmuContext.CASE:
if get_fmu_context_from_environment() != FmuContext.case:
raise RuntimeError(
"Only possible to run re-export of preprocessed data inside FMU "
"using a pre-simulation workflow in ERT."
)

self._fmudata = FmuProvider(
fmu_context=FmuContext.CASE,
fmu_context=FmuContext.case,
casepath_proposed=Path(self.casepath),
workflow=None,
)
Expand Down
4 changes: 2 additions & 2 deletions src/fmu/dataio/providers/_filedata.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from pathlib import Path
from typing import TYPE_CHECKING, Final, Optional

from fmu.dataio._definitions import FmuContext
from fmu.dataio._logging import null_logger
from fmu.dataio._utils import (
compute_md5_using_temp_file,
Expand Down Expand Up @@ -76,7 +75,8 @@ def parent(self) -> str:
def get_metadata(self) -> meta.File:
rootpath = (
self.runpath
if self.runpath and self.dataio.fmu_context == FmuContext.REALIZATION
if self.runpath
and self.dataio.fmu_context == meta.enums.FmuContext.realization
else self.dataio._rootpath
)
share_folders = self._get_share_folders()
Expand Down
18 changes: 9 additions & 9 deletions src/fmu/dataio/providers/_fmu.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@

from fmu.config import utilities as ut
from fmu.dataio import _utils
from fmu.dataio._definitions import FmuContext
from fmu.dataio._logging import null_logger
from fmu.dataio.datastructure._internal import internal
from fmu.dataio.datastructure.meta import meta
from fmu.dataio.datastructure.meta.enums import FmuContext
from fmu.dataio.exceptions import InvalidMetadataError

from ._base import Provider
Expand All @@ -55,13 +55,13 @@
logger: Final = null_logger(__name__)


def get_fmu_context_from_environment() -> FmuContext:
def get_fmu_context_from_environment() -> FmuContext | None:
"""return the ERT run context as an FmuContext"""
if FmuEnv.RUNPATH.value:
return FmuContext.REALIZATION
return FmuContext.realization
if FmuEnv.EXPERIMENT_ID.value:
return FmuContext.CASE
return FmuContext.NON_FMU
return FmuContext.case
return None


def _casepath_has_metadata(casepath: Path) -> bool:
Expand Down Expand Up @@ -104,7 +104,7 @@ class FmuProvider(Provider):
"""

model: dict | None = None
fmu_context: FmuContext = FmuContext.REALIZATION
fmu_context: FmuContext = FmuContext.realization
casepath_proposed: Optional[Path] = None
workflow: Optional[Union[str, dict[str, str]]] = None

Expand Down Expand Up @@ -135,7 +135,7 @@ def __post_init__(self) -> None:
if self._casepath:
self._case_name = self._casepath.name

if self._runpath and self.fmu_context != FmuContext.CASE:
if self._runpath and self.fmu_context != FmuContext.case:
missing_iter_folder = self._casepath == self._runpath.parent
if not missing_iter_folder:
logger.debug("Iteration folder found")
Expand Down Expand Up @@ -174,7 +174,7 @@ def get_metadata(self) -> internal.FMUClassMetaData:

case_meta = self._get_case_meta()

if self.fmu_context != FmuContext.REALIZATION:
if self.fmu_context != FmuContext.realization:
return internal.FMUClassMetaData(
case=case_meta.fmu.case,
context=self._get_fmucontext_meta(),
Expand Down Expand Up @@ -220,7 +220,7 @@ def _validate_and_establish_casepath(self) -> Path | None:
if _casepath_has_metadata(self._runpath.parent):
return self._runpath.parent

if self.fmu_context == FmuContext.CASE:
if self.fmu_context == FmuContext.case:
# TODO: Change to ValueError when no longer kwargs are accepted in export()
warn("Could not auto detect the casepath, please provide it as input.")

Expand Down
Loading

0 comments on commit 0ebdeb8

Please sign in to comment.