diff --git a/docs/generate_petro_jobs_for_field_update.rst b/docs/generate_petro_jobs_for_field_update.rst index 88a3eee3..1eb3f236 100644 --- a/docs/generate_petro_jobs_for_field_update.rst +++ b/docs/generate_petro_jobs_for_field_update.rst @@ -1,20 +1,22 @@ -rms.generate_petro_jobs_for_field_update -========================================= +rms.generate_petro_jobs +=========================== When running FMU project where field parameters for both facies and petrophysical properties is updated in ERT simultaneously, some adjustments are needed in the RMS project to support this type of workflow. It is necessary to have one petrosim job per facies. -To simplify the work with the RMS project, -the script *generate_petro_jobs_for_field_update* can be imported into -RMS as a python job. It requires a small configuration file and will then +To simplify the work with the RMS project, the function +*generate_petro_jobs* from *fmu.tools* +can be used in a python job in RMS. +It requires a small configuration file and will then read an existing petrosim job from the RMS project and generate one new petrosim job per facies. The new jobs are ready to be used (put into the RMS workflow) and they will use the same model parameters for the petrophysical properties as the original (existing) job, but only for one facies. -This script will modify your RMS project when run from your RMS project +The function *generate_petro_jobs* will modify +your RMS project when run from your RMS project by adding new petrosim jobs, one per facies as specified in the configuration file for the script. The configuration file is a yaml format file defining which grid model and which facies 3D parameter to use and the @@ -25,67 +27,66 @@ petrosim jobs that are generated. Usage ^^^^^ -Load the script *generate_petro_jobs_for_field_update* into a python job. -Specify a configuration file and specify the name of this configuration file in the -python job. +* Import the function *generate_petro_jobs* into a python job in RMS. + Specify a configuration file and specify the name of this configuration + file in the python job. -Run the python job in RMS to generate the new petrosim jobs and -finally update the workflowin RMS by using the generated jobs. +* Run the python job in RMS to generate the new petrosim jobs. + +* Finally, update the workflowin RMS by using the generated jobs. Example of python script in RMS .. code-block:: python - from fmu.tools.rms.generate_petro_jobs_for_field_update import main + from fmu.tools.rms import generate_petro_jobs CONFIG_FILE = "generate_petro_jobs.yml" if __name__ == "__main__": - main(CONFIG_FILE) + generate_petro_jobs(CONFIG_FILE) Example of configuration file for multi zone grid in RMS .. code-block:: yaml - # Name of grid model for the petrophysics jobs - grid_name: "MultiZoneBox" + # Name of grid model for the petrophysics jobs + grid_name: MultiZoneBox - # Name of original petro job using facies realization as input - original_job_name: "original_multi_zone" + # Name of original petro job using facies realization as input + original_job_name: original_multi_zone - # Use empty string as zone name for single zone grids and zone name - # for multizone grids. - # For each zone, specify facies and for each facies specify - # petro variables to be used as field parameters in ERT update + # Use empty string as zone name for single zone grids and zone name + # for multizone grids. + # For each zone, specify facies and for each facies specify + # petro variables to be used as field parameters in ERT update - # Example for a multizone grid with three zones: - used_petro_var: - Zone1: - F1: ["P1", "P2"] - F2: ["P1", "P2"] - F3: ["P1", "P2"] - Zone2: - F1: ["P1", "P2"] - F2: ["P1", "P2"] - F3: ["P1", "P2"] + # Example for a multizone grid with three zones: + used_petro_var: + Zone1: + F1: [P1, P2] + F2: [P1, P2] + F3: [P1, P2] + Zone2: + F1: [P1, P2] + F2: [P1, P2] + F3: [P1, P2] Example of configuration file for single zone grid in RMS .. code-block:: yaml - # Name of grid model for the petrophysics jobs - grid_name: "SingleZoneBox" - - # Name of original petro job using facies realization as input - original_job_name: "original_single_zone" - - # Use empty string as zone name for single zone grids and zone name - # for multizone grids. - # For each zone, specify facies and for each facies specify - # petro variables to be used as field parameters in ERT update - used_petro_var: - "": - F1: ["P1", "P2"] - F2: ["P1", "P2"] - F3: ["P1", "P2"] - - + # Name of grid model for the petrophysics jobs + grid_name: SingleZoneBox + + # Name of original petro job using facies realization as input + original_job_name: original_single_zone + + # Use empty string as zone name for single zone grids and zone name + # for multizone grids. + # For each zone, specify facies and for each facies specify + # petro variables to be used as field parameters in ERT update + used_petro_var: + default: + F1: [P1, P2] + F2: [P1, P2] + F3: [P1, P2] diff --git a/pyproject.toml b/pyproject.toml index af78bf9f..5128e657 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -79,7 +79,6 @@ ensemble_well_props = "fmu.tools.ensembles.ensemble_well_props:main" rename_rms_scripts = "fmu.tools.rms.rename_rms_scripts:main" rmsvolumetrics2csv = "fmu.tools.rms.volumetrics:rmsvolumetrics2csv_main" - [tool.ruff] line-length = 88 diff --git a/src/fmu/tools/rms/__init__.py b/src/fmu/tools/rms/__init__.py index 847641b2..0f2d6419 100644 --- a/src/fmu/tools/rms/__init__.py +++ b/src/fmu/tools/rms/__init__.py @@ -2,7 +2,14 @@ Processing of volumetrics from RMS """ +from .generate_petro_jobs_for_field_update import ( + main as generate_petro_jobs, +) from .import_localmodules import import_localmodule from .volumetrics import rmsvolumetrics_txt2df -__all__ = ["rmsvolumetrics_txt2df", "import_localmodule"] +__all__ = [ + "rmsvolumetrics_txt2df", + "import_localmodule", + "generate_petro_jobs", +] diff --git a/src/fmu/tools/rms/generate_petro_jobs_for_field_update.py b/src/fmu/tools/rms/generate_petro_jobs_for_field_update.py index 4a2a8646..ea064eef 100644 --- a/src/fmu/tools/rms/generate_petro_jobs_for_field_update.py +++ b/src/fmu/tools/rms/generate_petro_jobs_for_field_update.py @@ -1,66 +1,7 @@ """ Description: - This script can be used to generate new petrosim jobs in RMS from an existing - petrosim job. The input (original) petrosim job is assumed to be a job for either - a single zone or multi zone grid where the petrophysical properties are conditioned - to an existing facies realization. - The new generated petrosim jobs will not use facies realization as input, but assume - that all grid cells belongs to the same facies. Hence, if the original petrosim job - specify model parameters for petrophysical properties conditioned to a facies - realization with N different facies, this script can generate up to N new - petrosim jobs, one per facies the user wants to use in field parameter - updating in ERT. - -Input: - An existing RMS project with a petrophysical job conditioning petrophysical - properties on an existing facies realization. - - A yaml format configuration file specifying necessary input to the script. - This includes name of original petrosim job, grid model name and for each zone and - each facies which petrophysical variables to use in the new petrosim jobs that are - created. It is possible to not use all petrophysical variables in the original - job and this can vary from facies to facies and zone to zone. - -Output: - A set of new petrosim jobs, one per facies that is specified in at least - one of the zones. For a multi zone grid, each of the new petrosim jobs will - contain specification of the petrophysical properties that is to be modelled - for each zone for a given facies. The new jobs will get a name reflecting which - facies it belongs to. - -How to use the new petrosim jobs in the RMS workflow: - - When initial ensemble is created (ERT iteration = 0): - The RMS workflow should first use the original petrosim job to generate realizations - of petrophysical properties as usual when not all of the petrophysical properties - are going to be used as field parameters in RMS. If all petrophysical properties are - going to be updated as field parameters in ERT, it is not necessary to do this step. - Add all the new petrosim jobs (one per facies) into the workflow in RMS. - Copy the petrophysical property realizations for each facies from the geomodel grid - into the ERTBOX grid used for field parameter update in ERT. - Export the petrophysical properties for each of the facies to ERT in ROFF format. - Use a script that take as input the facies realization and the petrophysical - properties per facies and use the facies realization as filter to select which - values to copy from the petrophysical realizations to put into the petrophysical - property parameter that was generated by the original job. This will overwrite the - petrophysical properties in the realization from the original job for those - parameters that are used as field parameters to be updated by ERT. - The other petrophysical parameters generated by the original job but not used as - field parameters in ERT will be untouched. - - When updated ensemble is fetched from ERT (ERT iteration > 0): - Run the original petrosim job to generate all petrophysical parameters - in the geogrid. Import the updated field parameters for petrophysical properties - per facies into ERTBOX grid. - Copy the petrophysical property parameters that were updated as - field parameters by ERT into geomodel grid from the ERTBOX grid. - This operation is the same as the last step - when initial ensemble realization was created. This step will then overwrite the - petrophysical property parameters already created by the original job by the new - values updated by ERT. All petrophysical property parameters not updated as field - parameters by ERT will be untouched and will therefore have the same values as they - had after the original petrosim job was run. - + Implementation of a function to create new petrosim jobs, one per facies + given an existing petrosim job using facies realization as input. Summary: @@ -82,6 +23,7 @@ try: import _rmsapi as _roxar # type: ignore import roxar.jobs # type: ignore + import roxar.jobs.Job # type: ignore except ModuleNotFoundError: warnings.warn("This script only supports interactive RMS usage", UserWarning) from typing import no_type_check @@ -93,7 +35,103 @@ PP = pprint.PrettyPrinter(depth=7) -def main(config_file, debug=False, report_unused=False): +def main(config_file: str, debug: bool = False, report_unused: bool = False) -> None: + """Generate new RMS petrosim jobs from an original petrosim job. + + Description + + This function can be used to generate new petrosim jobs in RMS from an existing + petrosim job. The input (original) petrosim job is assumed to be a job for + either a single zone or multi zone grid where the petrophysical properties + are conditioned to an existing facies realization. + The new generated petrosim jobs will not use facies realization as input, + but assume that all grid cells belongs to the same facies. + Hence, if the original petrosim job specify model parameters for + petrophysical properties conditioned to a facies + realization with N different facies, this script can generate up to N new + petrosim jobs, one per facies the user wants to use in field parameter + updating in ERT. + + Input + + An existing RMS project with a petrophysical job conditioning petrophysical + properties on an existing facies realization. + + A yaml format configuration file specifying necessary input to the function. + This includes name of original petrosim job, grid model name and for each zone + and each facies which petrophysical variables to use in the new petrosim jobs + that are created. It is possible to not use all petrophysical variables in the + original job and this can vary from facies to facies and zone to zone. + + Output + + A set of new petrosim jobs, one per facies that is specified in at least + one of the zones. For a multi zone grid, each of the new petrosim jobs will + contain specification of the petrophysical properties that is to be modelled + for each zone for a given facies. The new jobs will get a name reflecting which + facies it belongs to. + + How to use the new petrosim jobs in the RMS workflow + + When initial ensemble is created (ERT iteration = 0) + + The RMS workflow should first use the original petrosim job to generate + realizations of petrophysical properties as usual when not all of the + petrophysical properties are going to be used as field parameters in RMS. + If all petrophysical properties are going to be updated as field parameters + in ERT, it is not necessary to do this step. + Add all the new petrosim jobs (one per facies) into the workflow in RMS. + Copy the petrophysical property realizations for each facies from the + geomodel grid into the ERTBOX grid used for field parameter update in ERT. + Export the petrophysical properties for each of the facies to ERT in + ROFF format. Use a script that take as input the facies realization and + the petrophysical properties per facies and use the facies realization + as filter to select which values to copy from the petrophysical realizations + to put into the petrophysical property parameter that was generated by + the original job. This will overwrite the petrophysical properties + in the realization from the original job for those + parameters that are used as field parameters to be updated by ERT. + The other petrophysical parameters generated by the original job but not + used as field parameters in ERT will be untouched. + + When updated ensemble is fetched from ERT (ERT iteration > 0): + + Run the original petrosim job to generate all petrophysical parameters + in the geogrid. Import the updated field parameters for petrophysical + properties per facies into ERTBOX grid. + Copy the petrophysical property parameters that were updated as + field parameters by ERT into geomodel grid from the ERTBOX grid. + This operation is the same as the last step + when initial ensemble realization was created. This step will then + overwrite the petrophysical property parameters already created by + the original job by the new values updated by ERT. All petrophysical + property parameters not updated as field parameters by ERT will be + untouched and will therefore have the same values as they + had after the original petrosim job was run. + + + Summary + + The current function is made to simplify the preparation step of the + RMS project by creating the necessary petrosim jobs for a workflow + supporting simultaneous update of both facies and petrophysical + properties in ERT. + + Usage of this function + + Input + Name of config file with specification of which field parameters + to simulate per zone per facies. + + Optional parameters + debug info (True/False), + report field parameters not used (True/False) + + Output + A set of new petro sim jobs to appear in RMS project. + + """ + spec_dict = read_specification_file(config_file) create_new_petro_job_per_facies( spec_dict, debug_print=debug, report_unused=report_unused @@ -106,7 +144,7 @@ def check_rms_project(project): raise RuntimeError("This run must be ran in an RoxAPI environment!") -def read_specification_file(config_file_name, check=True): +def read_specification_file(config_file_name: str, check: bool = True) -> dict: with open(config_file_name, encoding="utf-8") as yml_file: spec_dict = yaml.safe_load(yml_file) if check and (not check_specification(spec_dict)): @@ -114,7 +152,7 @@ def read_specification_file(config_file_name, check=True): return spec_dict -def check_specification(spec_dict): +def check_specification(spec_dict: dict) -> bool: # Check that the same petro variables are specified for # all zones using the same facies. This means that for instance # if the case has zone A,B,C and facies F1 is present in zone A and C @@ -160,8 +198,11 @@ def check_specification(spec_dict): def define_new_variable_names_and_correlation_matrix( - orig_var_names, facies_name, new_var_names, orig_corr_matrix -): + orig_var_names: list[str], + facies_name: str, + new_var_names: list[str], + orig_corr_matrix: list[list[float]], +) -> tuple[list[str], list[list[float]]]: nvar_new = len(new_var_names) if nvar_new == 1: # No correlation matrix @@ -195,7 +236,9 @@ def define_new_variable_names_and_correlation_matrix( return sorted_new_var_names, new_corr_matrix -def sort_new_var_names(original_variable_names, facies_name, new_variable_names): +def sort_new_var_names( + original_variable_names: list[str], facies_name: str, new_variable_names: list[str] +) -> list[str]: sorted_keep_list = [] for varname in original_variable_names: name = set_new_var_name(facies_name, varname) @@ -204,21 +247,26 @@ def sort_new_var_names(original_variable_names, facies_name, new_variable_names) return sorted_keep_list -def get_original_job_settings(owner_string_list, job_type, job_name): +def get_original_job_settings( + owner_string_list: list[str], job_type: str, job_name: str +) -> dict: original_job = roxar.jobs.Job.get_job(owner_string_list, job_type, job_name) return original_job.get_arguments(skip_defaults=False) def create_copy_of_job( - owner_string_list, job_type, original_job_arguments, new_job_name + owner_string_list: list[str], + job_type: str, + original_job_arguments: dict, + new_job_name: str, ): new_job = roxar.jobs.Job.create(owner_string_list, job_type, new_job_name) new_job.set_arguments(original_job_arguments) return new_job -def get_zone_names_per_facies(used_petro_per_zone_per_facies_dict): - zone_names_with_facies_dict = {} +def get_zone_names_per_facies(used_petro_per_zone_per_facies_dict: dict) -> dict: + zone_names_with_facies_dict: dict[str, list[str]] = {} for zone_name, facies_dict in used_petro_per_zone_per_facies_dict.items(): for facies_name, _ in facies_dict.items(): if facies_name not in zone_names_with_facies_dict: @@ -227,7 +275,7 @@ def get_zone_names_per_facies(used_petro_per_zone_per_facies_dict): return zone_names_with_facies_dict -def get_used_petro_names(used_petro_per_zone_per_facies_dict): +def get_used_petro_names(used_petro_per_zone_per_facies_dict: dict) -> list[str]: all_petro_var_list = [] for _, petro_per_facies_dict in used_petro_per_zone_per_facies_dict.items(): for _, petro_list in petro_per_facies_dict.items(): @@ -237,48 +285,57 @@ def get_used_petro_names(used_petro_per_zone_per_facies_dict): return all_petro_var_list -def set_new_var_name(facies_name, petro_name): +def set_new_var_name(facies_name: str, petro_name: str): return facies_name + "_" + petro_name -def check_consistency( - owner_string_list, job_name, used_petro_per_zone_per_facies_dict, report_unused=True +def report_unused_fields( + owner_string_list: list[str], + job_name: str, + used_petro_per_zone_per_facies_dict: dict, ): job_arguments = get_original_job_settings(owner_string_list, JOB_TYPE, job_name) zone_models_list = job_arguments["Zone Models"] + # First report which field parameters from original model + # that is not specified to be used + print("Report of unused petrophysical variables in generated jobs:") + for zone_model in zone_models_list: + zone_name = zone_model["ZoneName"] + if zone_name not in used_petro_per_zone_per_facies_dict: + print(f" No field parameters are used from zone: {zone_name}") + else: + petro_per_facies_dict = used_petro_per_zone_per_facies_dict[zone_name] + facies_models_list = zone_model["Facies Models"] + for facies_model in facies_models_list: + facies_name = facies_model["FaciesName"] + petro_model_list = facies_model["Variable Models"] + if facies_name not in petro_per_facies_dict: + print( + " No field parameters are used for facies " + f"{facies_name} for zone {zone_name}" + ) + else: + petro_list = petro_per_facies_dict[facies_name] + for petro_model in petro_model_list: + var_name = petro_model["VariableName"] + if var_name not in petro_list: + print( + f" Field parameter {var_name} is not used " + f"for facies {facies_name} for zone {zone_name}" + ) + print("") - if report_unused: - # First report which field parameters from original model - # that is not specified to be used - print("Report of unused petrophysical variables in generated jobs:") - for zone_model in zone_models_list: - zone_name = zone_model["ZoneName"] - if zone_name not in used_petro_per_zone_per_facies_dict: - print(f" No field parameters are used from zone: {zone_name}") - else: - petro_per_facies_dict = used_petro_per_zone_per_facies_dict[zone_name] - facies_models_list = zone_model["Facies Models"] - for facies_model in facies_models_list: - facies_name = facies_model["FaciesName"] - petro_model_list = facies_model["Variable Models"] - if facies_name not in petro_per_facies_dict: - print( - " No field parameters are used for facies " - f"{facies_name} for zone {zone_name}" - ) - else: - petro_list = petro_per_facies_dict[facies_name] - for petro_model in petro_model_list: - var_name = petro_model["VariableName"] - if var_name not in petro_list: - print( - f" Field parameter {var_name} is not used " - f"for facies {facies_name} for zone {zone_name}" - ) - print("") +def check_consistency( + owner_string_list: list[str], + job_name: str, + used_petro_per_zone_per_facies_dict: dict, + report_unused: bool = True, +) -> None: # Check if there are specified field parameters which does not exist # in the original job and report errors if this is the case + job_arguments = get_original_job_settings(owner_string_list, JOB_TYPE, job_name) + zone_models_list = job_arguments["Zone Models"] specified_petro_var_list = get_used_petro_names(used_petro_per_zone_per_facies_dict) err_list = [] for specified_petro_var in specified_petro_var_list: @@ -305,13 +362,27 @@ def check_consistency( raise ValueError("Unknown petrophysical variable names are specified.") -def create_new_petro_job_per_facies(spec_dict, debug_print=False, report_unused=False): +def create_new_petro_job_per_facies( + spec_dict: dict, debug_print: bool = False, report_unused: bool = False +) -> list[str]: grid_name = spec_dict["grid_name"] original_job_name = spec_dict["original_job_name"] used_petro_per_zone_per_facies_dict = spec_dict["used_petro_var"] + if len(used_petro_per_zone_per_facies_dict.keys()) == 1: + # Only one zone, set zone name to empty + zone_name = list(used_petro_per_zone_per_facies_dict.keys())[0] + tmp: dict[str, dict] = {} + tmp[""] = used_petro_per_zone_per_facies_dict[zone_name] + used_petro_per_zone_per_facies_dict = tmp + # Original job parameter setting owner_string_list = [GRID_MODELS, grid_name, GRID] + if report_unused: + report_unused_fields( + owner_string_list, original_job_name, used_petro_per_zone_per_facies_dict + ) + check_consistency( owner_string_list, original_job_name, @@ -444,7 +515,9 @@ def create_new_petro_job_per_facies(spec_dict, debug_print=False, report_unused= return new_job_name_list -def write_petro_job_to_file(owner_string_list, job_type, job_name, filename): +def write_petro_job_to_file( + owner_string_list: list[str], job_type: str, job_name: str, filename: str +) -> None: job_instance = roxar.jobs.Job.get_job( owner=owner_string_list, type=job_type, name=job_name ) diff --git a/tests/rms/generate_jobs_testdata/generate_original_multi_zone_job.yml b/tests/rms/generate_jobs_testdata/generate_original_multi_zone_job.yml index c5a4e4c6..13a5aec4 100644 --- a/tests/rms/generate_jobs_testdata/generate_original_multi_zone_job.yml +++ b/tests/rms/generate_jobs_testdata/generate_original_multi_zone_job.yml @@ -1,10 +1,10 @@ -grid_name: "MultiZoneBox" -grid_file_name: "multizonegrid.roff" -facies_real_name: "Facies" -facies_file_name: "multizonefacies.roff" -original_job_name: "original_multi_zone" +grid_name: MultiZoneBox +grid_file_name: multizonegrid.roff +facies_real_name: Facies +facies_file_name: multizonefacies.roff +original_job_name: original_multi_zone # mode is either: simulation or prediction -mode: "simulation" +mode: simulation original_job_settings: zones: Zone1: diff --git a/tests/rms/generate_jobs_testdata/generate_original_single_zone_job.yml b/tests/rms/generate_jobs_testdata/generate_original_single_zone_job.yml index 0d011de9..65ef8ee4 100644 --- a/tests/rms/generate_jobs_testdata/generate_original_single_zone_job.yml +++ b/tests/rms/generate_jobs_testdata/generate_original_single_zone_job.yml @@ -1,10 +1,10 @@ -grid_name: "SingleZoneBox" -grid_file_name: "singlezonegrid.roff" -facies_real_name: "Facies" -facies_file_name: "singlezonefacies.roff" -original_job_name: "original_single_zone" +grid_name: SingleZoneBox +grid_file_name: singlezonegrid.roff +facies_real_name: Facies +facies_file_name: singlezonefacies.roff +original_job_name: original_single_zone # mode is either: simulation or prediction -mode: "prediction" +mode: prediction original_job_settings: zones: "": diff --git a/tests/rms/generate_jobs_testdata/generate_petro_multi_zone_jobs.yml b/tests/rms/generate_jobs_testdata/generate_petro_multi_zone_jobs.yml index f541c65f..ebc4e809 100644 --- a/tests/rms/generate_jobs_testdata/generate_petro_multi_zone_jobs.yml +++ b/tests/rms/generate_jobs_testdata/generate_petro_multi_zone_jobs.yml @@ -1,8 +1,8 @@ # Name of grid model for the petrophysics jobs -grid_name: "MultiZoneBox" +grid_name: MultiZoneBox # Name of original petro job using facies realization as input -original_job_name: "original_multi_zone" +original_job_name: original_multi_zone # Use empty string as zone name for single zone grids and zone name for multizone grids. # For each zone, specify facies and for each facies specify @@ -11,13 +11,13 @@ original_job_name: "original_multi_zone" # Example for a multizone grid with three zones: used_petro_var: Zone1: - F1: ["P1", "P2"] - F2: ["P1", "P2"] - F3: ["P1", "P2"] + F1: [P1, P2] + F2: [P1, P2] + F3: [P1, P2] Zone2: - F1: ["P1", "P2"] - F2: ["P1", "P2"] - F3: ["P1", "P2"] + F1: [P1, P2] + F2: [P1, P2] + F3: [P1, P2] diff --git a/tests/rms/generate_jobs_testdata/generate_petro_single_zone_jobs.yml b/tests/rms/generate_jobs_testdata/generate_petro_single_zone_jobs.yml index dfa2bb1c..42b10dac 100644 --- a/tests/rms/generate_jobs_testdata/generate_petro_single_zone_jobs.yml +++ b/tests/rms/generate_jobs_testdata/generate_petro_single_zone_jobs.yml @@ -1,14 +1,14 @@ # Name of grid model for the petrophysics jobs -grid_name: "SingleZoneBox" +grid_name: SingleZoneBox # Name of original petro job using facies realization as input -original_job_name: "original_single_zone" +original_job_name: original_single_zone -# Use empty string as zone name for single zone grids and zone name for multizone grids. +# Use default as zone name for single zone grids and zone name for multizone grids. # For each zone, specify facies and for each facies specify # petro variables to be used as field parameters in ERT update used_petro_var: - "": - F1: ["P1", "P2"] - F2: ["P1", "P2"] - F3: ["P1", "P2"] + default: + F1: [P1, P2] + F2: [P1, P2] + F3: [P1, P2] diff --git a/tests/rms/test_generate_petro_jobs_for_field_update.py b/tests/rms/test_generate_petro_jobs_for_field_update.py index c697bc6d..0f275f15 100644 --- a/tests/rms/test_generate_petro_jobs_for_field_update.py +++ b/tests/rms/test_generate_petro_jobs_for_field_update.py @@ -17,13 +17,13 @@ from pathlib import Path import pytest -import xtgeo +import xtgeo # type: ignore with contextlib.suppress(ImportError): import roxar # type: ignore import roxar.jobs # type: ignore -from fmu.tools.rms.generate_petro_jobs_for_field_update import ( +from fmu.tools.rms.generate_petro_jobs_for_field_update import ( # type: ignore check_rms_project, create_new_petro_job_per_facies, define_new_variable_names_and_correlation_matrix, @@ -44,7 +44,7 @@ RESULTDIR = TMPD / "jobs" RESULTDIR.mkdir(parents=True, exist_ok=True) -REFERENCE_DIR = Path("rms/generate_jobs_testdata") +REFERENCE_DIR = Path("tests/rms/generate_jobs_testdata") CONFIG_FILE_ORIGINAL_SINGLE_ZONE_JOB = ( REFERENCE_DIR / "generate_original_single_zone_job.yml" ) @@ -73,7 +73,7 @@ @pytest.mark.parametrize( "original_variable_names, facies_name, new_variable_names_input, " - "original_Lcorr_mat, reference_var_names, reference_corr_mat", + "original_lower_corr_mat, reference_var_names, reference_corr_mat", [ ( ["phit", "vsh", "klogh", "vphyl"], @@ -102,26 +102,26 @@ ], ) def test_define_new_variable_names_and_correlation_matrix( - original_variable_names, - facies_name, - new_variable_names_input, - original_Lcorr_mat, - reference_var_names, - reference_corr_mat, -): - new_variable_names, new_Lcorr_mat = ( + original_variable_names: list[str], + facies_name: str, + new_variable_names_input: list[str], + original_lower_corr_mat: list[list[float]], + reference_var_names: list[str], + reference_corr_mat: list[list[float]], +) -> None: + new_variable_names, new_lower_corr_mat = ( define_new_variable_names_and_correlation_matrix( original_variable_names, facies_name, new_variable_names_input, - original_Lcorr_mat, + original_lower_corr_mat, ) ) print(f"Original var names: {original_variable_names}") print(f"New var names: {new_variable_names}") - print(f"Original correlations: {original_Lcorr_mat}") - print(f"New correlations: {new_Lcorr_mat}") + print(f"Original correlations: {original_lower_corr_mat}") + print(f"New correlations: {new_lower_corr_mat}") # Compare lists with reference l1 = new_variable_names @@ -130,16 +130,16 @@ def test_define_new_variable_names_and_correlation_matrix( assert len(res) == 0 # Compare corr matrix with reference - nrows = len(new_Lcorr_mat) + nrows = len(new_lower_corr_mat) assert nrows == len(reference_corr_mat) for j in range(nrows): - ncol = len(new_Lcorr_mat[j]) + ncol = len(new_lower_corr_mat[j]) assert ncol == len(reference_corr_mat[j]) for i in range(ncol): - assert new_Lcorr_mat[j][i] == reference_corr_mat[j][i] + assert new_lower_corr_mat[j][i] == reference_corr_mat[j][i] -def create_original_petro_job(spec_dict): +def create_original_petro_job(spec_dict: dict) -> str: grid_name = spec_dict["grid_name"] owner_string_list = ["Grid models", grid_name, "Grid"] job_name = spec_dict["original_job_name"] @@ -163,7 +163,7 @@ def create_original_petro_job(spec_dict): return job_name -def define_setting_for_original_job(spec_dict): +def define_setting_for_original_job(spec_dict: dict) -> dict: # Use specified zones, facies and variable names and selected model parameters, # but assign default to all other settings facies_real_name = spec_dict["facies_real_name"] @@ -258,7 +258,7 @@ def define_setting_for_original_job(spec_dict): } -def rename_subgrids(xtgeo_grd): +def rename_subgrids(xtgeo_grd: xtgeo.Grid) -> None: nsubgrids = len(list(xtgeo_grd.subgrids.keys())) subgrid_names = [] for i in range(nsubgrids): @@ -269,8 +269,6 @@ def rename_subgrids(xtgeo_grd): # Here the temporary RMS project is created. It contains a grid, # a facies parameter and an original petrophysical job -# @pytest.mark.skipunlessroxar -# @pytest.fixture def create_project(): """Create a tmp RMS project for testing, populate with basic data. @@ -350,7 +348,7 @@ def create_project(): # as the original petro job for the # petrophysical properties. @pytest.mark.skipunlessroxar -def test_generate_jobs(): +def test_generate_jobs() -> None: """Test generate_petro_jobs_for_field_update""" project = create_project() @@ -363,11 +361,11 @@ def test_generate_jobs(): filename = RESULTDIR / Path(job_name + "_single.txt") reference_filename = REFERENCE_FILES_SINGLE_ZONE_GRID[n] write_petro_job_to_file(OWNER_STRING_SINGLE_ZONE, JOB_TYPE, job_name, filename) - # Compare text files with job parameters with reference for single zone jobs - check = filecmp.cmp(filename, reference_filename) - if check: - print("Check OK for single zone grid") - assert check + # Compare text files with job parameters with reference for single zone jobs + check = filecmp.cmp(filename, reference_filename) + if check: + print("Check OK for single zone grid") + assert check for n, job_name in enumerate(job_name_list): petro_job = roxar.jobs.Job.get_job(OWNER_STRING_SINGLE_ZONE, JOB_TYPE, job_name) @@ -381,11 +379,11 @@ def test_generate_jobs(): filename = RESULTDIR / Path(job_name + "_multi.txt") reference_filename = REFERENCE_FILES_MULTI_ZONE_GRID[n] write_petro_job_to_file(OWNER_STRING_MULTI_ZONE, JOB_TYPE, job_name, filename) - # Compare text files with job parameters with reference for single zone jobs - check = filecmp.cmp(filename, reference_filename) - if check: - print("Check OK for multi zone grid") - assert check + # Compare text files with job parameters with reference for single zone jobs + check = filecmp.cmp(filename, reference_filename) + if check: + print("Check OK for multi zone grid") + assert check for n, job_name in enumerate(job_name_list): petro_job = roxar.jobs.Job.get_job(OWNER_STRING_MULTI_ZONE, JOB_TYPE, job_name)