Skip to content

Commit

Permalink
Add support for design matrix keyword in ert config
Browse files Browse the repository at this point in the history
  • Loading branch information
larsevj committed Sep 26, 2024
1 parent e2d3a90 commit 7cb27a8
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/ert/config/analysis_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
ConfigKeys,
ConfigValidationError,
ConfigWarning,
ErrorInfo,
)

logger = logging.getLogger(__name__)

DEFAULT_ANALYSIS_MODE = AnalysisMode.ENSEMBLE_SMOOTHER
ObservationGroups = List[str]
from ._option_dict import option_dict


@dataclass
Expand All @@ -31,6 +33,45 @@ class UpdateSettings:
auto_scale_observations: List[ObservationGroups] = field(default_factory=list)


@dataclass
class DesignMatrixArgs:
xls_filename: Path
designsheet: str
defaultsheet: str

@classmethod
def from_config_list(cls, config_list: List[str]) -> "DesignMatrixArgs":
filename = Path(config_list[0])
options = option_dict(config_list, 1)
design_sheet = options.get("DESIGN_SHEET")
default_sheet = options.get("DEFAULT_SHEET")
errors = []
if filename.suffix not in {
".xlsx",
".xls",
}:
errors.append(
ErrorInfo(
f"DESIGN_MATRIX must be of format .xls or .xslx; is {filename}"
).set_context(config_list)
)
if design_sheet is None:
errors.append(
ErrorInfo("Missing required DESIGN_SHEET").set_context(config_list)
)
if default_sheet is None:
errors.append(
ErrorInfo("Missing required DEFAULT_SHEET").set_context(config_list)
)
if errors:
raise ConfigValidationError.from_collected(errors)
return cls(
xls_filename=filename,
designsheet=design_sheet,

Check failure on line 70 in src/ert/config/analysis_config.py

View workflow job for this annotation

GitHub Actions / type-checking (3.12)

Argument "designsheet" to "DesignMatrixArgs" has incompatible type "str | None"; expected "str"
defaultsheet=default_sheet,

Check failure on line 71 in src/ert/config/analysis_config.py

View workflow job for this annotation

GitHub Actions / type-checking (3.12)

Argument "defaultsheet" to "DesignMatrixArgs" has incompatible type "str | None"; expected "str"
)


@dataclass
class AnalysisConfig:
max_runtime: Optional[int] = None
Expand All @@ -40,6 +81,7 @@ class AnalysisConfig:
ies_module: IESSettings = field(default_factory=IESSettings)
observation_settings: UpdateSettings = field(default_factory=UpdateSettings)
num_iterations: int = 1
design_matrix_args: Optional[DesignMatrixArgs] = None

@no_type_check
@classmethod
Expand Down Expand Up @@ -78,6 +120,9 @@ def from_dict(cls, config_dict: ConfigDict) -> "AnalysisConfig":
)

min_realization = min(min_realization, num_realization)

design_matrix_config_list = config_dict.get(ConfigKeys.DESIGN_MATRIX, None)

options: Dict[str, Dict[str, Any]] = {"STD_ENKF": {}, "IES_ENKF": {}}
observation_settings: Dict[str, Any] = {
"alpha": config_dict.get(ConfigKeys.ENKF_ALPHA, 3.0),
Expand Down Expand Up @@ -189,6 +234,11 @@ def from_dict(cls, config_dict: ConfigDict) -> "AnalysisConfig":
observation_settings=obs_settings,
es_module=es_settings,
ies_module=ies_settings,
design_matrix_args=DesignMatrixArgs.from_config_list(
design_matrix_config_list
)
if design_matrix_config_list is not None
else None,
)
return config

Expand Down
1 change: 1 addition & 0 deletions src/ert/config/parsing/config_keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class ConfigKeys(StrEnum):
JOB_SCRIPT = "JOB_SCRIPT"
JOBNAME = "JOBNAME"
MAX_SUBMIT = "MAX_SUBMIT"
DESIGN_MATRIX = "DESIGN_MATRIX"
NUM_REALIZATIONS = "NUM_REALIZATIONS"
MIN_REALIZATIONS = "MIN_REALIZATIONS"
OBS_CONFIG = "OBS_CONFIG"
Expand Down
15 changes: 15 additions & 0 deletions src/ert/config/parsing/config_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,20 @@ def install_job_directory_keyword() -> SchemaItem:
)


def design_matrix_keyword() -> SchemaItem:
return SchemaItem(
kw=ConfigKeys.DESIGN_MATRIX,
argc_min=3,
argc_max=3,
type_map=[
SchemaItemType.EXISTING_PATH,
SchemaItemType.STRING,
SchemaItemType.STRING,
],
multi_occurrence=False,
)


class ConfigSchemaDict(SchemaItemDict):
def check_required(
self,
Expand Down Expand Up @@ -345,6 +359,7 @@ def init_user_config_schema() -> ConfigSchemaDict:
positive_int_keyword(ConfigKeys.NUM_CPU),
positive_int_keyword(ConfigKeys.MAX_RUNNING),
string_keyword(ConfigKeys.REALIZATION_MEMORY),
design_matrix_keyword(),
queue_system_keyword(False),
queue_option_keyword(),
job_script_keyword(),
Expand Down
23 changes: 23 additions & 0 deletions tests/ert/unit_tests/config/test_analysis_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def test_analysis_config_from_file_is_same_as_from_dict():
NUM_REALIZATIONS 10
MIN_REALIZATIONS 10
ANALYSIS_SET_VAR STD_ENKF ENKF_TRUNCATION 0.8
DESIGN_MATRIX my_design_matrix.xlsx DESIGN_SHEET:my_sheet DEFAULT_SHEET:my_default_sheet
"""
)
).analysis_config == AnalysisConfig.from_dict(
Expand All @@ -30,6 +31,11 @@ def test_analysis_config_from_file_is_same_as_from_dict():
ConfigKeys.ANALYSIS_SET_VAR: [
("STD_ENKF", "ENKF_TRUNCATION", 0.8),
],
ConfigKeys.DESIGN_MATRIX: [
"my_design_matrix.xlsx"
"DESIGN_SHEET:my_sheet"
"DEFAULT_SHEET:my_default_sheet"
],
}
)

Expand Down Expand Up @@ -80,6 +86,23 @@ def test_invalid_min_realization_raises_config_validation_error():
)


def test_invalid_design_matrix_format_raises_validation_error():
with pytest.raises(
ConfigValidationError,
match="DESIGN_MATRIX must be of format .xls or .xslx; is 'my_matrix.txt'",
):
AnalysisConfig.from_dict(
{
ConfigKeys.NUM_REALIZATIONS: 1,
ConfigKeys.DESIGN_MATRIX: [
"my_matrix.txt",
"DESIGN_SHEET:sheet1",
"DEFAULT_SHEET:sheet2",
],
}
)


def test_invalid_min_realization_percentage_raises_config_validation_error():
with pytest.raises(
ConfigValidationError,
Expand Down

0 comments on commit 7cb27a8

Please sign in to comment.