diff --git a/src/semeio/forward_models/__init__.py b/src/semeio/forward_models/__init__.py index 979795b5..5f687407 100644 --- a/src/semeio/forward_models/__init__.py +++ b/src/semeio/forward_models/__init__.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Callable, Optional from ert import ( ForwardModelStepDocumentation, @@ -8,6 +8,17 @@ from .scripts.design2params import description as design2params_description from .scripts.design_kw import description as design_kw_description +from .scripts.design_kw import design_kw as DesignKWScript + + +def validation_enabled(validation_func: Callable) -> Callable[..., None]: + def wrapper( + self: ForwardModelStepPlugin, fm_step_json: ForwardModelStepJSON + ) -> None: + if self.private_args.get("", "").lower() == "true": + validation_func(self, fm_step_json) + + return wrapper class Design2Params(ForwardModelStepPlugin): @@ -45,7 +56,8 @@ class DesignKW(ForwardModelStepPlugin): def __init__(self): super().__init__( name="DESIGN_KW", - command=["design_kw", "", ""], + command=["design_kw", "", "", ""], + default_mapping={"": "false"}, ) def validate_pre_realization_run( @@ -53,8 +65,11 @@ def validate_pre_realization_run( ) -> ForwardModelStepJSON: return fm_step_json + @validation_enabled def validate_pre_experiment(self, fm_step_json: ForwardModelStepJSON) -> None: - pass + template_file_name = self.private_args[""] + DesignKWScript.validate_configuration(template_file_name=template_file_name) + return fm_step_json @staticmethod def documentation() -> Optional[ForwardModelStepDocumentation]: diff --git a/src/semeio/forward_models/design_kw/design_kw.py b/src/semeio/forward_models/design_kw/design_kw.py index 0557c630..6449f2b8 100644 --- a/src/semeio/forward_models/design_kw/design_kw.py +++ b/src/semeio/forward_models/design_kw/design_kw.py @@ -1,11 +1,15 @@ import logging +import os import re import shlex from typing import List +from ert.config.forward_model_step import ForwardModelStepWarning + _STATUS_FILE_NAME = "DESIGN_KW.OK" _logger = logging.getLogger(__name__) +errors = [] def run( @@ -65,7 +69,9 @@ def all_matched(line, template_file_name, template): f"but this is probably an xml file" ) else: - _logger.error(f"{unmatched} not found in design matrix") + error_msg = f"{unmatched} not found in design matrix" + _logger.error(error_msg) + errors.append(error_msg) valid = False return valid @@ -178,3 +184,41 @@ def rm_genkw_prefix(paramsdict, ignoreprefixes="LOG10_"): for keyvalue in keyvalues if keys.count(keyvalue[0]) == 1 } + + +def validate_configuration( + template_file_name: str, parameters_file_name: str = "parameters.txt" +) -> None: + try: + if not os.path.exists(template_file_name): + raise ValueError( + f"Argument template_file: '{template_file_name}' is not an existing file" + ) + + if not os.path.exists(parameters_file_name): + raise ValueError( + f"Could not find required parameters file from DESIGN2PARAMS: '{parameters_file_name}'" + ) + with open(parameters_file_name, encoding="utf-8") as parameters_file: + parameters = parameters_file.readlines() + + key_vals = extract_key_value(parameters) + + key_vals.update(rm_genkw_prefix(key_vals)) + + with open(template_file_name, encoding="utf-8") as template_file: + template = template_file.readlines() + + for line in template: + if not is_comment(line): + for key, value in key_vals.items(): + line = line.replace(f"<{key}>", str(value)) + + all_matched(line, template_file_name, template) + + except ValueError as e: + errors.append(str(e)) + + if errors: + error_message = f"DESIGN_KW configuration validation failed:\n{errors}" + ForwardModelStepWarning.warn(error_message) diff --git a/src/semeio/forward_models/scripts/design_kw.py b/src/semeio/forward_models/scripts/design_kw.py index 84669e31..a249473c 100755 --- a/src/semeio/forward_models/scripts/design_kw.py +++ b/src/semeio/forward_models/scripts/design_kw.py @@ -20,6 +20,8 @@ Example: If ``parameters.txt`` has the line ``MULTFLT:FLT_A10_B18 0.001``, both of the templates ```` and ```` will expand to ``0.001``. + +Configuration validation pre experiment can be disabled by explicitly setting ``=false`` """ @@ -44,7 +46,7 @@ def create_parser(): default="WARNING", type=logging.getLevelName, ) - + parser.add_argument("--validate", required=False, type=bool, default=True) return parser