diff --git a/src/ert/config/_read_summary.py b/src/ert/config/_read_summary.py index 3c98e7c27dd..8b3c6b9567e 100644 --- a/src/ert/config/_read_summary.py +++ b/src/ert/config/_read_summary.py @@ -23,73 +23,7 @@ import resfo from pydantic import PositiveInt -SPECIAL_KEYWORDS = [ - "NEWTON", - "NAIMFRAC", - "NLINEARS", - "NLINSMIN", - "NLINSMAX", - "ELAPSED", - "MAXDPR", - "MAXDSO", - "MAXDSG", - "MAXDSW", - "STEPTYPE", - "WNEWTON", -] - - -class _SummaryType(Enum): - AQUIFER = auto() - BLOCK = auto() - COMPLETION = auto() - FIELD = auto() - GROUP = auto() - LOCAL_BLOCK = auto() - LOCAL_COMPLETION = auto() - LOCAL_WELL = auto() - NETWORK = auto() - SEGMENT = auto() - WELL = auto() - REGION = auto() - INTER_REGION = auto() - OTHER = auto() - - @classmethod - def from_keyword(cls, summary_keyword: str) -> _SummaryType: - KEYWORD_TYPE_MAPPING = { - "A": cls.AQUIFER, - "B": cls.BLOCK, - "C": cls.COMPLETION, - "F": cls.FIELD, - "G": cls.GROUP, - "LB": cls.LOCAL_BLOCK, - "LC": cls.LOCAL_COMPLETION, - "LW": cls.LOCAL_WELL, - "N": cls.NETWORK, - "S": cls.SEGMENT, - "W": cls.WELL, - } - if not summary_keyword: - raise ValueError("Got empty summary keyword") - if any(special in summary_keyword for special in SPECIAL_KEYWORDS): - return cls.OTHER - if summary_keyword[0] in KEYWORD_TYPE_MAPPING: - return KEYWORD_TYPE_MAPPING[summary_keyword[0]] - if summary_keyword[0:2] in KEYWORD_TYPE_MAPPING: - return KEYWORD_TYPE_MAPPING[summary_keyword[0:2]] - if summary_keyword == "RORFR": - return cls.REGION - - if any( - re.fullmatch(pattern, summary_keyword) - for pattern in [r"R.FT.*", r"R..FT.*", r"R.FR.*", r"R..FR.*", r"R.F"] - ): - return cls.INTER_REGION - if summary_keyword[0] == "R": - return cls.REGION - - return cls.OTHER +from ert.summary_key_type import SummaryKeyType def _cell_index( @@ -128,53 +62,53 @@ def make_summary_key( lj: Optional[int] = None, lk: Optional[int] = None, ) -> Optional[str]: - sum_type = _SummaryType.from_keyword(keyword) + sum_type = SummaryKeyType.from_keyword(keyword) if sum_type in [ - _SummaryType.FIELD, - _SummaryType.OTHER, + SummaryKeyType.FIELD, + SummaryKeyType.OTHER, ]: return keyword if sum_type in [ - _SummaryType.REGION, - _SummaryType.AQUIFER, + SummaryKeyType.REGION, + SummaryKeyType.AQUIFER, ]: return f"{keyword}:{number}" - if sum_type == _SummaryType.BLOCK: + if sum_type == SummaryKeyType.BLOCK: nx, ny = _check_if_missing("block", "dimens", nx, ny) (number,) = _check_if_missing("block", "nums", number) i, j, k = _cell_index(number - 1, nx, ny) return f"{keyword}:{i},{j},{k}" if sum_type in [ - _SummaryType.GROUP, - _SummaryType.WELL, + SummaryKeyType.GROUP, + SummaryKeyType.WELL, ]: return f"{keyword}:{name}" - if sum_type == _SummaryType.SEGMENT: + if sum_type == SummaryKeyType.SEGMENT: return f"{keyword}:{name}:{number}" - if sum_type == _SummaryType.COMPLETION: + if sum_type == SummaryKeyType.COMPLETION: nx, ny = _check_if_missing("completion", "dimens", nx, ny) (number,) = _check_if_missing("completion", "nums", number) i, j, k = _cell_index(number - 1, nx, ny) return f"{keyword}:{name}:{i},{j},{k}" - if sum_type == _SummaryType.INTER_REGION: + if sum_type == SummaryKeyType.INTER_REGION: (number,) = _check_if_missing("inter region", "nums", number) r1 = number % 32768 r2 = ((number - r1) // 32768) - 10 return f"{keyword}:{r1}-{r2}" - if sum_type == _SummaryType.LOCAL_WELL: + if sum_type == SummaryKeyType.LOCAL_WELL: (name,) = _check_if_missing("local well", "WGNAMES", name) (lgr_name,) = _check_if_missing("local well", "LGRS", lgr_name) return f"{keyword}:{lgr_name}:{name}" - if sum_type == _SummaryType.LOCAL_BLOCK: + if sum_type == SummaryKeyType.LOCAL_BLOCK: li, lj, lk = _check_if_missing("local block", "NUMLX", li, lj, lk) (lgr_name,) = _check_if_missing("local block", "LGRS", lgr_name) return f"{keyword}:{lgr_name}:{li},{lj},{lk}" - if sum_type == _SummaryType.LOCAL_COMPLETION: + if sum_type == SummaryKeyType.LOCAL_COMPLETION: li, lj, lk = _check_if_missing("local completion", "NUMLX", li, lj, lk) (name,) = _check_if_missing("local completion", "WGNAMES", name) (lgr_name,) = _check_if_missing("local completion", "LGRS", lgr_name) return f"{keyword}:{lgr_name}:{name}:{li},{lj},{lk}" - if sum_type == _SummaryType.NETWORK: + if sum_type == SummaryKeyType.NETWORK: (name,) = _check_if_missing("network", "WGNAMES", name) return f"{keyword}:{name}" raise ValueError(f"Unexpected keyword type: {sum_type}") diff --git a/src/ert/gui/plottery/plots/ensemble.py b/src/ert/gui/plottery/plots/ensemble.py index 58dd3ab0d9a..2171f03c04b 100644 --- a/src/ert/gui/plottery/plots/ensemble.py +++ b/src/ert/gui/plottery/plots/ensemble.py @@ -7,7 +7,7 @@ from ert.gui.plottery.plots.history import plotHistory from ert.gui.tools.plot.plot_api import EnsembleObject -from ert.shared.storage.summary_key_utils import is_rate +from ert.summary_key_type import is_rate from .observations import plotObservations from .plot_tools import PlotTools diff --git a/src/ert/shared/storage/summary_key_utils.py b/src/ert/summary_key_type.py similarity index 61% rename from src/ert/shared/storage/summary_key_utils.py rename to src/ert/summary_key_type.py index 998195caaac..611f5928a08 100644 --- a/src/ert/shared/storage/summary_key_utils.py +++ b/src/ert/summary_key_type.py @@ -1,7 +1,12 @@ +from __future__ import annotations + +import re from enum import Enum, auto -from typing import List +from typing import ( + List, +) -special_keys = [ +SPECIAL_KEYWORDS = [ "NAIMFRAC", "NBAKFL", "NBYTOT", @@ -29,6 +34,61 @@ "STEPTYPE", "WNEWTON", ] + + +class SummaryKeyType(Enum): + AQUIFER = auto() + BLOCK = auto() + COMPLETION = auto() + FIELD = auto() + GROUP = auto() + LOCAL_BLOCK = auto() + LOCAL_COMPLETION = auto() + LOCAL_WELL = auto() + NETWORK = auto() + SEGMENT = auto() + WELL = auto() + REGION = auto() + INTER_REGION = auto() + OTHER = auto() + + @classmethod + def from_keyword(cls, summary_keyword: str) -> SummaryKeyType: + KEYWORD_TYPE_MAPPING = { + "A": cls.AQUIFER, + "B": cls.BLOCK, + "C": cls.COMPLETION, + "F": cls.FIELD, + "G": cls.GROUP, + "LB": cls.LOCAL_BLOCK, + "LC": cls.LOCAL_COMPLETION, + "LW": cls.LOCAL_WELL, + "N": cls.NETWORK, + "S": cls.SEGMENT, + "W": cls.WELL, + } + if not summary_keyword: + raise ValueError("Got empty summary keyword") + if any(special in summary_keyword for special in SPECIAL_KEYWORDS): + return cls.OTHER + if summary_keyword[0] in KEYWORD_TYPE_MAPPING: + return KEYWORD_TYPE_MAPPING[summary_keyword[0]] + if summary_keyword[0:2] in KEYWORD_TYPE_MAPPING: + return KEYWORD_TYPE_MAPPING[summary_keyword[0:2]] + if summary_keyword == "RORFR": + return cls.REGION + + if any( + re.fullmatch(pattern, summary_keyword) + for pattern in [r"R.FT.*", r"R..FT.*", r"R.FR.*", r"R..FR.*", r"R.F"] + ): + return cls.INTER_REGION + if summary_keyword[0] == "R": + return cls.REGION + + return cls.OTHER + + rate_keys = [ "OPR", "OIR", @@ -100,62 +160,6 @@ ] -class SummaryKeyType(Enum): - INVALID = auto() - FIELD = auto() - REGION = auto() - GROUP = auto() - WELL = auto() - SEGMENT = auto() - BLOCK = auto() - AQUIFER = auto() - COMPLETION = auto() - NETWORK = auto() - REGION_2_REGION = auto() - LOCAL_BLOCK = auto() - LOCAL_COMPLETION = auto() - LOCAL_WELL = auto() - MISC = auto() - - @staticmethod - def determine_key_type(key: str) -> "SummaryKeyType": - if key in special_keys: - return SummaryKeyType.MISC - - if key.startswith("L"): - secondary = key[1] if len(key) > 1 else "" - return { - "B": SummaryKeyType.LOCAL_BLOCK, - "C": SummaryKeyType.LOCAL_COMPLETION, - "W": SummaryKeyType.LOCAL_WELL, - }.get(secondary, SummaryKeyType.MISC) - - if key.startswith("R"): - if len(key) == 3 and key[2] == "F": - return SummaryKeyType.REGION_2_REGION - if key == "RNLF": - return SummaryKeyType.REGION_2_REGION - if key == "RORFR": - return SummaryKeyType.REGION - if len(key) >= 4 and key[2] == "F" and key[3] in {"T", "R"}: - return SummaryKeyType.REGION_2_REGION - if len(key) >= 5 and key[3] == "F" and key[4] in {"T", "R"}: - return SummaryKeyType.REGION_2_REGION - return SummaryKeyType.REGION - - # default cases or miscellaneous if not matched - return { - "A": SummaryKeyType.AQUIFER, - "B": SummaryKeyType.BLOCK, - "C": SummaryKeyType.COMPLETION, - "F": SummaryKeyType.FIELD, - "G": SummaryKeyType.GROUP, - "N": SummaryKeyType.NETWORK, - "S": SummaryKeyType.SEGMENT, - "W": SummaryKeyType.WELL, - }.get(key[0], SummaryKeyType.MISC) - - def _match_keyword_vector(start: int, rate_keys: List[str], keyword: str) -> bool: if len(keyword) < start: return False @@ -169,7 +173,7 @@ def _match_keyword_string(start: int, rate_string: str, keyword: str) -> bool: def is_rate(key: str) -> bool: - key_type = SummaryKeyType.determine_key_type(key) + key_type = SummaryKeyType.from_keyword(key) if key_type in { SummaryKeyType.WELL, SummaryKeyType.GROUP, @@ -191,7 +195,7 @@ def is_rate(key: str) -> bool: if key_type == SummaryKeyType.SEGMENT: return _match_keyword_vector(1, seg_rate_keys, key) - if key_type == SummaryKeyType.REGION_2_REGION: + if key_type == SummaryKeyType.INTER_REGION: # Region to region rates are identified by R*FR or R**FR if _match_keyword_string(2, "FR", key): return True diff --git a/tests/unit_tests/config/summary_generator.py b/tests/unit_tests/config/summary_generator.py index 3e3a544bb6b..8ae2cd82fda 100644 --- a/tests/unit_tests/config/summary_generator.py +++ b/tests/unit_tests/config/summary_generator.py @@ -17,7 +17,7 @@ from pydantic import PositiveInt, conint from typing_extensions import Self -from ert.config._read_summary import SPECIAL_KEYWORDS +from ert.summary_key_type import SPECIAL_KEYWORDS from .egrid_generator import GrdeclKeyword diff --git a/tests/unit_tests/config/test_read_summary.py b/tests/unit_tests/config/test_read_summary.py index efc5b959569..001f90f41ca 100644 --- a/tests/unit_tests/config/test_read_summary.py +++ b/tests/unit_tests/config/test_read_summary.py @@ -7,7 +7,8 @@ from hypothesis import given from resdata.summary import Summary, SummaryVarType -from ert.config._read_summary import _SummaryType, make_summary_key, read_summary +from ert.config._read_summary import make_summary_key, read_summary +from ert.summary_key_type import SummaryKeyType from .summary_generator import ( inter_region_summary_variables, @@ -16,118 +17,118 @@ ) -def to_ecl(st: _SummaryType) -> SummaryVarType: - if st == _SummaryType.AQUIFER: +def to_ecl(st: SummaryKeyType) -> SummaryVarType: + if st == SummaryKeyType.AQUIFER: return SummaryVarType.RD_SMSPEC_AQUIFER_VAR - if st == _SummaryType.BLOCK: + if st == SummaryKeyType.BLOCK: return SummaryVarType.RD_SMSPEC_BLOCK_VAR - if st == _SummaryType.COMPLETION: + if st == SummaryKeyType.COMPLETION: return SummaryVarType.RD_SMSPEC_COMPLETION_VAR - if st == _SummaryType.FIELD: + if st == SummaryKeyType.FIELD: return SummaryVarType.RD_SMSPEC_FIELD_VAR - if st == _SummaryType.GROUP: + if st == SummaryKeyType.GROUP: return SummaryVarType.RD_SMSPEC_GROUP_VAR - if st == _SummaryType.LOCAL_BLOCK: + if st == SummaryKeyType.LOCAL_BLOCK: return SummaryVarType.RD_SMSPEC_LOCAL_BLOCK_VAR - if st == _SummaryType.LOCAL_COMPLETION: + if st == SummaryKeyType.LOCAL_COMPLETION: return SummaryVarType.RD_SMSPEC_LOCAL_COMPLETION_VAR - if st == _SummaryType.LOCAL_WELL: + if st == SummaryKeyType.LOCAL_WELL: return SummaryVarType.RD_SMSPEC_LOCAL_WELL_VAR - if st == _SummaryType.NETWORK: + if st == SummaryKeyType.NETWORK: return SummaryVarType.RD_SMSPEC_NETWORK_VAR - if st == _SummaryType.SEGMENT: + if st == SummaryKeyType.SEGMENT: return SummaryVarType.RD_SMSPEC_SEGMENT_VAR - if st == _SummaryType.WELL: + if st == SummaryKeyType.WELL: return SummaryVarType.RD_SMSPEC_WELL_VAR - if st == _SummaryType.REGION: + if st == SummaryKeyType.REGION: return SummaryVarType.RD_SMSPEC_REGION_VAR - if st == _SummaryType.INTER_REGION: + if st == SummaryKeyType.INTER_REGION: return SummaryVarType.RD_SMSPEC_REGION_2_REGION_VAR - if st == _SummaryType.OTHER: + if st == SummaryKeyType.OTHER: return SummaryVarType.RD_SMSPEC_MISC_VAR @pytest.mark.parametrize("keyword", ["AAQR", "AAQT"]) def test_aquifer_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_AQUIFER_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.AQUIFER + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.AQUIFER @pytest.mark.parametrize("keyword", ["BOSAT"]) def test_block_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_BLOCK_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.BLOCK + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.BLOCK @pytest.mark.parametrize("keyword", ["LBOSAT"]) def test_local_block_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_LOCAL_BLOCK_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.LOCAL_BLOCK + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.LOCAL_BLOCK @pytest.mark.parametrize("keyword", ["CGORL"]) def test_completion_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_COMPLETION_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.COMPLETION + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.COMPLETION @pytest.mark.parametrize("keyword", ["LCGORL"]) def test_local_completion_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_LOCAL_COMPLETION_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.LOCAL_COMPLETION + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.LOCAL_COMPLETION @pytest.mark.parametrize("keyword", ["FGOR", "FOPR"]) def test_field_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_FIELD_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.FIELD + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.FIELD @pytest.mark.parametrize("keyword", ["GGFT", "GOPR"]) def test_group_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_GROUP_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.GROUP + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.GROUP @pytest.mark.parametrize("keyword", ["NOPR", "NGPR"]) def test_network_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_NETWORK_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.NETWORK + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.NETWORK @pytest.mark.parametrize("keyword", inter_region_summary_variables) def test_inter_region_summary_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_REGION_2_REGION_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.INTER_REGION + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.INTER_REGION @pytest.mark.parametrize("keyword", ["RORFR", "RPR", "ROPT"]) def test_region_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_REGION_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.REGION + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.REGION @pytest.mark.parametrize("keyword", ["SOPR"]) def test_segment_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_SEGMENT_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.SEGMENT + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.SEGMENT @pytest.mark.parametrize("keyword", ["WOPR"]) def test_well_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_WELL_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.WELL + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.WELL @pytest.mark.parametrize("keyword", ["LWOPR"]) def test_local_well_variables_are_recognized(keyword): assert Summary.var_type(keyword) == SummaryVarType.RD_SMSPEC_LOCAL_WELL_VAR - assert _SummaryType.from_keyword(keyword) == _SummaryType.LOCAL_WELL + assert SummaryKeyType.from_keyword(keyword) == SummaryKeyType.LOCAL_WELL @given(summary_variables()) def test_that_identify_var_type_is_same_as_ecl(variable): - assert Summary.var_type(variable) == to_ecl(_SummaryType.from_keyword(variable)) + assert Summary.var_type(variable) == to_ecl(SummaryKeyType.from_keyword(variable)) @given(st.integers(), st.text(), st.integers(), st.integers()) diff --git a/tests/unit_tests/gui/plottery/test_ensemble_plot.py b/tests/unit_tests/gui/plottery/test_ensemble_plot.py index f6778a56b23..758fb79234a 100644 --- a/tests/unit_tests/gui/plottery/test_ensemble_plot.py +++ b/tests/unit_tests/gui/plottery/test_ensemble_plot.py @@ -7,7 +7,7 @@ from ert.gui.plottery import PlotConfig, PlotContext from ert.gui.plottery.plots.ensemble import EnsemblePlot from ert.gui.tools.plot.plot_api import EnsembleObject -from ert.shared.storage.summary_key_utils import is_rate +from ert.summary_key_type import is_rate @pytest.fixture( diff --git a/tests/unit_tests/shared/test_rate_keys.py b/tests/unit_tests/shared/test_rate_keys.py index 63cc0d34ede..5262174e422 100644 --- a/tests/unit_tests/shared/test_rate_keys.py +++ b/tests/unit_tests/shared/test_rate_keys.py @@ -3,7 +3,7 @@ from hypothesis import given from resdata.summary import Summary -from ert.shared.storage.summary_key_utils import is_rate +from ert.summary_key_type import is_rate from tests.unit_tests.config.summary_generator import summary_variables