ert 16.0.9__py3-none-any.whl → 19.0.0rc2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- _ert/events.py +19 -2
- _ert/forward_model_runner/client.py +6 -2
- _ert/forward_model_runner/fm_dispatch.py +9 -6
- _ert/forward_model_runner/reporting/event.py +1 -0
- _ert/forward_model_runner/runner.py +1 -2
- _ert/utils.py +12 -0
- ert/__main__.py +58 -38
- ert/analysis/_enif_update.py +8 -4
- ert/analysis/_es_update.py +19 -6
- ert/analysis/_update_commons.py +16 -6
- ert/base_model_context.py +1 -1
- ert/cli/main.py +17 -12
- ert/cli/monitor.py +7 -0
- ert/config/__init__.py +17 -6
- ert/config/_create_observation_dataframes.py +118 -21
- ert/config/_get_num_cpu.py +1 -1
- ert/config/_observations.py +91 -2
- ert/config/_read_summary.py +74 -328
- ert/config/design_matrix.py +62 -23
- ert/config/distribution.py +1 -1
- ert/config/ensemble_config.py +9 -17
- ert/config/ert_config.py +155 -58
- ert/config/everest_control.py +234 -0
- ert/config/{everest_constraints_config.py → everest_response.py} +27 -15
- ert/config/field.py +99 -90
- ert/config/forward_model_step.py +122 -17
- ert/config/gen_data_config.py +5 -10
- ert/config/gen_kw_config.py +11 -41
- ert/config/known_response_types.py +14 -0
- ert/config/parameter_config.py +1 -33
- ert/config/parsing/_option_dict.py +10 -2
- ert/config/parsing/config_errors.py +1 -1
- ert/config/parsing/config_keywords.py +2 -1
- ert/config/parsing/config_schema.py +23 -11
- ert/config/parsing/config_schema_deprecations.py +3 -3
- ert/config/parsing/config_schema_item.py +26 -11
- ert/config/parsing/context_values.py +3 -3
- ert/config/parsing/file_context_token.py +1 -1
- ert/config/parsing/observations_parser.py +6 -2
- ert/config/parsing/queue_system.py +9 -0
- ert/config/parsing/schema_item_type.py +1 -0
- ert/config/queue_config.py +42 -50
- ert/config/response_config.py +0 -8
- ert/config/rft_config.py +275 -0
- ert/config/summary_config.py +3 -8
- ert/config/surface_config.py +73 -26
- ert/config/workflow_fixtures.py +2 -1
- ert/config/workflow_job.py +135 -54
- ert/dark_storage/client/__init__.py +2 -2
- ert/dark_storage/client/_session.py +4 -4
- ert/dark_storage/client/client.py +2 -2
- ert/dark_storage/common.py +12 -3
- ert/dark_storage/compute/misfits.py +11 -7
- ert/dark_storage/endpoints/compute/misfits.py +6 -4
- ert/dark_storage/endpoints/ensembles.py +4 -0
- ert/dark_storage/endpoints/experiment_server.py +30 -24
- ert/dark_storage/endpoints/experiments.py +2 -2
- ert/dark_storage/endpoints/observations.py +8 -6
- ert/dark_storage/endpoints/parameters.py +4 -12
- ert/dark_storage/endpoints/responses.py +24 -5
- ert/dark_storage/json_schema/ensemble.py +3 -0
- ert/dark_storage/json_schema/experiment.py +1 -1
- ert/data/_measured_data.py +6 -5
- ert/ensemble_evaluator/__init__.py +8 -1
- ert/ensemble_evaluator/config.py +2 -1
- ert/ensemble_evaluator/evaluator.py +81 -29
- ert/ensemble_evaluator/event.py +6 -0
- ert/ensemble_evaluator/snapshot.py +3 -1
- ert/ensemble_evaluator/state.py +1 -0
- ert/field_utils/__init__.py +8 -0
- ert/field_utils/field_utils.py +228 -15
- ert/field_utils/grdecl_io.py +1 -1
- ert/field_utils/roff_io.py +1 -1
- ert/gui/__init__.py +5 -2
- ert/gui/ertnotifier.py +1 -1
- ert/gui/ertwidgets/__init__.py +23 -16
- ert/gui/ertwidgets/analysismoduleedit.py +2 -2
- ert/gui/ertwidgets/checklist.py +1 -1
- ert/gui/ertwidgets/closabledialog.py +2 -0
- ert/gui/ertwidgets/copyablelabel.py +2 -0
- ert/gui/ertwidgets/create_experiment_dialog.py +3 -1
- ert/gui/ertwidgets/ensembleselector.py +2 -2
- ert/gui/ertwidgets/listeditbox.py +2 -0
- ert/gui/ertwidgets/models/__init__.py +2 -0
- ert/gui/ertwidgets/models/activerealizationsmodel.py +5 -1
- ert/gui/ertwidgets/models/path_model.py +1 -1
- ert/gui/ertwidgets/models/targetensemblemodel.py +5 -1
- ert/gui/ertwidgets/models/text_model.py +4 -1
- ert/gui/ertwidgets/pathchooser.py +0 -3
- ert/gui/ertwidgets/searchbox.py +17 -4
- ert/gui/ertwidgets/stringbox.py +2 -0
- ert/gui/{suggestor → ertwidgets/suggestor}/_suggestor_message.py +13 -4
- ert/gui/{suggestor → ertwidgets/suggestor}/suggestor.py +63 -30
- ert/gui/main.py +41 -13
- ert/gui/main_window.py +3 -7
- ert/gui/model/fm_step_list.py +3 -0
- ert/gui/model/real_list.py +1 -0
- ert/gui/model/snapshot.py +1 -0
- ert/gui/simulation/combobox_with_description.py +3 -0
- ert/gui/simulation/ensemble_experiment_panel.py +8 -2
- ert/gui/simulation/ensemble_information_filter_panel.py +7 -2
- ert/gui/simulation/ensemble_smoother_panel.py +8 -2
- ert/gui/simulation/evaluate_ensemble_panel.py +17 -7
- ert/gui/simulation/experiment_panel.py +18 -6
- ert/gui/simulation/manual_update_panel.py +35 -10
- ert/gui/simulation/multiple_data_assimilation_panel.py +13 -9
- ert/gui/simulation/run_dialog.py +47 -20
- ert/gui/simulation/single_test_run_panel.py +6 -3
- ert/gui/simulation/view/progress_widget.py +2 -0
- ert/gui/simulation/view/realization.py +5 -1
- ert/gui/simulation/view/update.py +2 -0
- ert/gui/summarypanel.py +20 -1
- ert/gui/tools/event_viewer/panel.py +3 -4
- ert/gui/tools/event_viewer/tool.py +2 -0
- ert/gui/tools/load_results/load_results_panel.py +1 -1
- ert/gui/tools/load_results/load_results_tool.py +2 -0
- ert/gui/tools/manage_experiments/export_dialog.py +136 -0
- ert/gui/tools/manage_experiments/manage_experiments_panel.py +2 -0
- ert/gui/tools/manage_experiments/storage_info_widget.py +121 -16
- ert/gui/tools/manage_experiments/storage_widget.py +4 -3
- ert/gui/tools/plot/customize/color_chooser.py +5 -2
- ert/gui/tools/plot/customize/customize_plot_dialog.py +2 -0
- ert/gui/tools/plot/customize/default_customization_view.py +4 -0
- ert/gui/tools/plot/customize/limits_customization_view.py +3 -0
- ert/gui/tools/plot/customize/statistics_customization_view.py +3 -0
- ert/gui/tools/plot/customize/style_chooser.py +2 -0
- ert/gui/tools/plot/customize/style_customization_view.py +3 -0
- ert/gui/tools/plot/data_type_keys_widget.py +2 -0
- ert/gui/tools/plot/data_type_proxy_model.py +3 -0
- ert/gui/tools/plot/plot_api.py +50 -28
- ert/gui/tools/plot/plot_ensemble_selection_widget.py +17 -10
- ert/gui/tools/plot/plot_widget.py +15 -2
- ert/gui/tools/plot/plot_window.py +41 -19
- ert/gui/tools/plot/plottery/plot_config.py +2 -0
- ert/gui/tools/plot/plottery/plot_context.py +14 -0
- ert/gui/tools/plot/plottery/plots/__init__.py +2 -0
- ert/gui/tools/plot/plottery/plots/cesp.py +3 -1
- ert/gui/tools/plot/plottery/plots/distribution.py +6 -1
- ert/gui/tools/plot/plottery/plots/ensemble.py +13 -5
- ert/gui/tools/plot/plottery/plots/gaussian_kde.py +12 -2
- ert/gui/tools/plot/plottery/plots/histogram.py +3 -1
- ert/gui/tools/plot/plottery/plots/misfits.py +436 -0
- ert/gui/tools/plot/plottery/plots/observations.py +18 -4
- ert/gui/tools/plot/plottery/plots/statistics.py +62 -20
- ert/gui/tools/plot/plottery/plots/std_dev.py +3 -1
- ert/gui/tools/plot/widgets/clearable_line_edit.py +9 -0
- ert/gui/tools/plot/widgets/filter_popup.py +2 -0
- ert/gui/tools/plot/widgets/filterable_kw_list_model.py +3 -0
- ert/gui/tools/plugins/plugin.py +1 -1
- ert/gui/tools/plugins/plugins_tool.py +2 -0
- ert/gui/tools/plugins/process_job_dialog.py +3 -0
- ert/gui/tools/workflows/workflow_dialog.py +2 -0
- ert/gui/tools/workflows/workflows_tool.py +2 -0
- ert/libres_facade.py +5 -7
- ert/logging/__init__.py +4 -1
- ert/mode_definitions.py +2 -0
- ert/plugins/__init__.py +4 -6
- ert/plugins/hook_implementations/workflows/csv_export.py +2 -3
- ert/plugins/hook_implementations/workflows/gen_data_rft_export.py +10 -2
- ert/plugins/hook_specifications/__init__.py +0 -10
- ert/plugins/hook_specifications/jobs.py +0 -9
- ert/plugins/plugin_manager.py +53 -124
- ert/resources/forward_models/run_reservoirsimulator.py +8 -4
- ert/resources/forward_models/template_render.py +10 -10
- ert/resources/shell_scripts/delete_directory.py +2 -2
- ert/run_models/__init__.py +24 -6
- ert/run_models/_create_run_path.py +133 -38
- ert/run_models/ensemble_experiment.py +10 -4
- ert/run_models/ensemble_information_filter.py +8 -1
- ert/run_models/ensemble_smoother.py +9 -3
- ert/run_models/evaluate_ensemble.py +8 -6
- ert/run_models/event.py +7 -3
- ert/run_models/everest_run_model.py +337 -113
- ert/run_models/initial_ensemble_run_model.py +25 -24
- ert/run_models/manual_update.py +6 -3
- ert/run_models/manual_update_enif.py +37 -0
- ert/run_models/model_factory.py +78 -18
- ert/run_models/multiple_data_assimilation.py +22 -11
- ert/run_models/run_model.py +72 -73
- ert/run_models/single_test_run.py +7 -4
- ert/run_models/update_run_model.py +4 -2
- ert/runpaths.py +5 -6
- ert/sample_prior.py +9 -4
- ert/scheduler/__init__.py +10 -5
- ert/scheduler/driver.py +40 -0
- ert/scheduler/event.py +3 -1
- ert/scheduler/job.py +23 -13
- ert/scheduler/lsf_driver.py +15 -5
- ert/scheduler/openpbs_driver.py +10 -4
- ert/scheduler/scheduler.py +5 -0
- ert/scheduler/slurm_driver.py +20 -5
- ert/services/__init__.py +2 -2
- ert/services/_base_service.py +37 -20
- ert/services/_storage_main.py +20 -18
- ert/services/ert_server.py +317 -0
- ert/shared/_doc_utils/__init__.py +4 -2
- ert/shared/_doc_utils/ert_jobs.py +1 -4
- ert/shared/net_utils.py +43 -18
- ert/shared/storage/connection.py +3 -3
- ert/shared/version.py +3 -3
- ert/storage/__init__.py +14 -1
- ert/storage/local_ensemble.py +44 -13
- ert/storage/local_experiment.py +54 -34
- ert/storage/local_storage.py +90 -58
- ert/storage/migration/to10.py +3 -2
- ert/storage/migration/to11.py +9 -10
- ert/storage/migration/to12.py +19 -20
- ert/storage/migration/to13.py +28 -27
- ert/storage/migration/to14.py +3 -3
- ert/storage/migration/to15.py +25 -0
- ert/storage/migration/to16.py +38 -0
- ert/storage/migration/to17.py +42 -0
- ert/storage/migration/to18.py +11 -0
- ert/storage/migration/to19.py +34 -0
- ert/storage/migration/to20.py +23 -0
- ert/storage/migration/to21.py +25 -0
- ert/storage/migration/to6.py +3 -2
- ert/storage/migration/to7.py +12 -13
- ert/storage/migration/to8.py +9 -11
- ert/storage/migration/to9.py +5 -4
- ert/storage/realization_storage_state.py +7 -7
- ert/substitutions.py +12 -28
- ert/validation/active_range.py +7 -7
- ert/validation/ensemble_realizations_argument.py +4 -2
- ert/validation/rangestring.py +16 -16
- ert/workflow_runner.py +6 -3
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/METADATA +21 -15
- ert-19.0.0rc2.dist-info/RECORD +524 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/WHEEL +1 -1
- everest/api/everest_data_api.py +14 -1
- everest/assets/everest_logo.svg +406 -0
- everest/bin/config_branch_script.py +30 -14
- everest/bin/everconfigdump_script.py +2 -10
- everest/bin/everest_script.py +53 -33
- everest/bin/everlint_script.py +3 -5
- everest/bin/kill_script.py +7 -5
- everest/bin/main.py +11 -24
- everest/bin/monitor_script.py +64 -35
- everest/bin/utils.py +58 -43
- everest/bin/visualization_script.py +23 -13
- everest/config/__init__.py +4 -1
- everest/config/control_config.py +81 -6
- everest/config/control_variable_config.py +4 -3
- everest/config/everest_config.py +102 -79
- everest/config/forward_model_config.py +5 -3
- everest/config/install_data_config.py +7 -5
- everest/config/install_job_config.py +45 -3
- everest/config/install_template_config.py +3 -3
- everest/config/optimization_config.py +19 -6
- everest/config/output_constraint_config.py +8 -2
- everest/config/server_config.py +6 -55
- everest/config/simulator_config.py +62 -17
- everest/config/utils.py +25 -105
- everest/config/validation_utils.py +34 -15
- everest/config_file_loader.py +30 -21
- everest/detached/__init__.py +0 -6
- everest/detached/client.py +7 -52
- everest/detached/everserver.py +19 -45
- everest/everest_storage.py +24 -40
- everest/gui/everest_client.py +2 -3
- everest/gui/main_window.py +2 -2
- everest/optimizer/everest2ropt.py +68 -42
- everest/optimizer/opt_model_transforms.py +15 -20
- everest/optimizer/utils.py +0 -29
- everest/plugins/hook_specs.py +0 -24
- everest/strings.py +1 -6
- everest/util/__init__.py +3 -1
- ert/config/everest_objective_config.py +0 -95
- ert/config/ext_param_config.py +0 -107
- ert/gui/tools/export/__init__.py +0 -3
- ert/gui/tools/export/export_panel.py +0 -83
- ert/gui/tools/export/export_tool.py +0 -67
- ert/gui/tools/export/exporter.py +0 -36
- ert/plugins/hook_specifications/ecl_config.py +0 -29
- ert/services/storage_service.py +0 -127
- ert/summary_key_type.py +0 -234
- ert-16.0.9.dist-info/RECORD +0 -521
- everest/bin/everexport_script.py +0 -53
- everest/config/sampler_config.py +0 -103
- everest/simulator/__init__.py +0 -88
- everest/simulator/everest_to_ert.py +0 -252
- /ert/gui/{suggestor → ertwidgets/suggestor}/__init__.py +0 -0
- /ert/gui/{suggestor → ertwidgets/suggestor}/_colors.py +0 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/entry_points.txt +0 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/licenses/COPYING +0 -0
- {ert-16.0.9.dist-info → ert-19.0.0rc2.dist-info}/top_level.txt +0 -0
ert/config/ensemble_config.py
CHANGED
|
@@ -7,30 +7,22 @@ from typing import Self
|
|
|
7
7
|
|
|
8
8
|
from pydantic import BaseModel, Field, model_validator
|
|
9
9
|
|
|
10
|
-
from .
|
|
10
|
+
from .everest_control import EverestControl
|
|
11
11
|
from .field import Field as FieldConfig
|
|
12
|
-
from .gen_data_config import GenDataConfig
|
|
13
12
|
from .gen_kw_config import GenKwConfig
|
|
13
|
+
from .known_response_types import KNOWN_ERT_RESPONSE_TYPES, KnownErtResponseTypes
|
|
14
14
|
from .parameter_config import ParameterConfig
|
|
15
15
|
from .parsing import ConfigDict, ConfigKeys, ConfigValidationError
|
|
16
16
|
from .response_config import ResponseConfig
|
|
17
|
-
from .summary_config import SummaryConfig
|
|
18
17
|
from .surface_config import SurfaceConfig
|
|
19
18
|
|
|
20
|
-
KnownResponseTypes = SummaryConfig | GenDataConfig
|
|
21
|
-
|
|
22
|
-
_KNOWN_RESPONSE_TYPES = (
|
|
23
|
-
SummaryConfig,
|
|
24
|
-
GenDataConfig,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
19
|
logger = logging.getLogger(__name__)
|
|
28
20
|
|
|
29
21
|
|
|
30
22
|
class EnsembleConfig(BaseModel):
|
|
31
|
-
response_configs: dict[str,
|
|
23
|
+
response_configs: dict[str, KnownErtResponseTypes] = Field(default_factory=dict)
|
|
32
24
|
parameter_configs: dict[
|
|
33
|
-
str, GenKwConfig | FieldConfig | SurfaceConfig |
|
|
25
|
+
str, GenKwConfig | FieldConfig | SurfaceConfig | EverestControl
|
|
34
26
|
] = Field(default_factory=dict)
|
|
35
27
|
|
|
36
28
|
@model_validator(mode="after")
|
|
@@ -131,16 +123,16 @@ class EnsembleConfig(BaseModel):
|
|
|
131
123
|
+ [make_field(f) for f in field_list]
|
|
132
124
|
)
|
|
133
125
|
EnsembleConfig._check_for_duplicate_gen_kw_param_names(gen_kw_cfgs)
|
|
134
|
-
response_configs: list[
|
|
126
|
+
response_configs: list[KnownErtResponseTypes] = []
|
|
135
127
|
|
|
136
|
-
for config_cls in
|
|
128
|
+
for config_cls in KNOWN_ERT_RESPONSE_TYPES:
|
|
137
129
|
instance = config_cls.from_config_dict(config_dict)
|
|
138
130
|
|
|
139
131
|
if instance is not None and instance.keys:
|
|
140
132
|
response_configs.append(instance)
|
|
141
133
|
|
|
142
134
|
return cls(
|
|
143
|
-
response_configs={response.
|
|
135
|
+
response_configs={response.type: response for response in response_configs},
|
|
144
136
|
parameter_configs={
|
|
145
137
|
parameter.name: parameter for parameter in parameter_configs
|
|
146
138
|
},
|
|
@@ -151,13 +143,13 @@ class EnsembleConfig(BaseModel):
|
|
|
151
143
|
return self.parameter_configs[key]
|
|
152
144
|
elif key in self.response_configs:
|
|
153
145
|
return self.response_configs[key]
|
|
154
|
-
elif
|
|
146
|
+
elif config := next(
|
|
155
147
|
(c for c in self.response_configs.values() if key in c.keys), None
|
|
156
148
|
):
|
|
157
149
|
# Only hit by blockfs migration
|
|
158
150
|
# returns the same config for one call per
|
|
159
151
|
# response type. Is later deduped before saving to json
|
|
160
|
-
return
|
|
152
|
+
return config
|
|
161
153
|
else:
|
|
162
154
|
raise KeyError(f"The key:{key} is not in the ensemble configuration")
|
|
163
155
|
|
ert/config/ert_config.py
CHANGED
|
@@ -25,6 +25,7 @@ from ._design_matrix_validator import DesignMatrixValidator
|
|
|
25
25
|
from ._observations import (
|
|
26
26
|
HistoryObservation,
|
|
27
27
|
Observation,
|
|
28
|
+
RFTObservation,
|
|
28
29
|
SummaryObservation,
|
|
29
30
|
make_observations,
|
|
30
31
|
)
|
|
@@ -36,9 +37,12 @@ from .forward_model_step import (
|
|
|
36
37
|
ForwardModelStepJSON,
|
|
37
38
|
ForwardModelStepValidationError,
|
|
38
39
|
ForwardModelStepWarning,
|
|
40
|
+
SiteInstalledForwardModelStep,
|
|
41
|
+
SiteOrUserForwardModelStep,
|
|
42
|
+
UserInstalledForwardModelStep,
|
|
39
43
|
)
|
|
40
44
|
from .gen_data_config import GenDataConfig
|
|
41
|
-
from .gen_kw_config import GenKwConfig
|
|
45
|
+
from .gen_kw_config import DataSource, GenKwConfig
|
|
42
46
|
from .model_config import ModelConfig
|
|
43
47
|
from .parse_arg_types_list import parse_arg_types_list
|
|
44
48
|
from .parsing import (
|
|
@@ -59,9 +63,11 @@ from .parsing import (
|
|
|
59
63
|
from .parsing.observations_parser import ObservationDict
|
|
60
64
|
from .queue_config import KnownQueueOptions, QueueConfig
|
|
61
65
|
from .refcase import Refcase
|
|
66
|
+
from .rft_config import RFTConfig
|
|
62
67
|
from .workflow import Workflow
|
|
63
68
|
from .workflow_fixtures import fixtures_per_hook
|
|
64
69
|
from .workflow_job import (
|
|
70
|
+
BaseErtScriptWorkflow,
|
|
65
71
|
ErtScriptLoadFailure,
|
|
66
72
|
ErtScriptWorkflow,
|
|
67
73
|
WorkflowJob,
|
|
@@ -132,6 +138,7 @@ def create_forward_model_json(
|
|
|
132
138
|
env_pr_fm_step = {}
|
|
133
139
|
|
|
134
140
|
context_substitutions = Substitutions(context)
|
|
141
|
+
real_iter_substituter = context_substitutions.real_iter_substituter(iens, itr)
|
|
135
142
|
|
|
136
143
|
class Substituter:
|
|
137
144
|
def __init__(self, fm_step: ForwardModelStep) -> None:
|
|
@@ -145,7 +152,7 @@ def create_forward_model_json(
|
|
|
145
152
|
)
|
|
146
153
|
self.copy_private_args = Substitutions(
|
|
147
154
|
{
|
|
148
|
-
key:
|
|
155
|
+
key: real_iter_substituter.substitute(val)
|
|
149
156
|
for key, val in fm_step.private_args.items()
|
|
150
157
|
}
|
|
151
158
|
)
|
|
@@ -162,7 +169,7 @@ def create_forward_model_json(
|
|
|
162
169
|
string = self.copy_private_args.substitute(
|
|
163
170
|
string, self.substitution_context_hint, 1, warn_max_iter=False
|
|
164
171
|
)
|
|
165
|
-
return
|
|
172
|
+
return real_iter_substituter.substitute(string)
|
|
166
173
|
|
|
167
174
|
def filter_env_dict(self, env_dict: dict[str, str]) -> dict[str, str] | None:
|
|
168
175
|
substituted_dict = {}
|
|
@@ -323,63 +330,74 @@ def read_templates(config_dict: ConfigDict) -> list[tuple[str, str]]:
|
|
|
323
330
|
|
|
324
331
|
def workflow_jobs_from_dict(
|
|
325
332
|
content_dict: ConfigDict,
|
|
326
|
-
|
|
333
|
+
site_installed_workflows_jobs: dict[str, WorkflowJob] | None = None,
|
|
327
334
|
) -> dict[str, WorkflowJob]:
|
|
328
|
-
|
|
329
|
-
|
|
335
|
+
user_installed_workflow_job_info = content_dict.get(
|
|
336
|
+
ConfigKeys.LOAD_WORKFLOW_JOB, []
|
|
337
|
+
)
|
|
338
|
+
user_installed_workflow_job_dir_info = content_dict.get(
|
|
339
|
+
ConfigKeys.WORKFLOW_JOB_DIRECTORY, []
|
|
340
|
+
)
|
|
330
341
|
|
|
331
|
-
workflow_jobs =
|
|
342
|
+
workflow_jobs = (
|
|
343
|
+
copy.copy(site_installed_workflows_jobs)
|
|
344
|
+
if site_installed_workflows_jobs
|
|
345
|
+
else {}
|
|
346
|
+
)
|
|
332
347
|
|
|
333
348
|
errors: list[ErrorInfo | ConfigValidationError] = []
|
|
334
349
|
|
|
335
|
-
for
|
|
350
|
+
for user_workflow_job in user_installed_workflow_job_info:
|
|
336
351
|
try:
|
|
337
352
|
# workflow_job_from_file only throws error if a
|
|
338
353
|
# non-readable file is provided.
|
|
339
354
|
# Non-existing files are caught by the new parser
|
|
340
|
-
|
|
341
|
-
config_file=
|
|
342
|
-
name=None if len(
|
|
355
|
+
user_job = workflow_job_from_file(
|
|
356
|
+
config_file=user_workflow_job[0],
|
|
357
|
+
name=None if len(user_workflow_job) == 1 else user_workflow_job[1],
|
|
358
|
+
origin="user",
|
|
343
359
|
)
|
|
344
|
-
name =
|
|
360
|
+
name = user_job.name
|
|
345
361
|
if name in workflow_jobs:
|
|
346
362
|
ConfigWarning.warn(
|
|
347
363
|
f"Duplicate workflow jobs with name {name!r}, choosing "
|
|
348
|
-
f"{
|
|
364
|
+
f"{user_job.location()!r} over "
|
|
349
365
|
f"{workflow_jobs[name].location()!r}",
|
|
350
366
|
name,
|
|
351
367
|
)
|
|
352
|
-
workflow_jobs[name] =
|
|
368
|
+
workflow_jobs[name] = user_job
|
|
353
369
|
except ErtScriptLoadFailure as err:
|
|
354
370
|
ConfigWarning.warn(
|
|
355
|
-
f"Loading workflow job {
|
|
371
|
+
f"Loading workflow job {user_workflow_job[0]!r}"
|
|
356
372
|
f" failed with '{err}'. It will not be loaded.",
|
|
357
|
-
|
|
373
|
+
user_workflow_job[0],
|
|
358
374
|
)
|
|
359
375
|
except ConfigValidationError as err:
|
|
360
|
-
errors.append(ErrorInfo(message=str(err)).set_context(
|
|
376
|
+
errors.append(ErrorInfo(message=str(err)).set_context(user_workflow_job[0]))
|
|
361
377
|
|
|
362
|
-
for
|
|
363
|
-
for
|
|
378
|
+
for user_job_path in user_installed_workflow_job_dir_info:
|
|
379
|
+
for user_job_file in _get_files_in_directory(user_job_path, errors):
|
|
364
380
|
try:
|
|
365
|
-
|
|
366
|
-
|
|
381
|
+
user_job = workflow_job_from_file(
|
|
382
|
+
config_file=user_job_file, origin="user"
|
|
383
|
+
)
|
|
384
|
+
name = user_job.name
|
|
367
385
|
if name in workflow_jobs:
|
|
368
386
|
ConfigWarning.warn(
|
|
369
387
|
f"Duplicate workflow jobs with name {name!r}, choosing "
|
|
370
|
-
f"{
|
|
388
|
+
f"{user_job.location()!r} over "
|
|
371
389
|
f"{workflow_jobs[name].location()!r}",
|
|
372
390
|
name,
|
|
373
391
|
)
|
|
374
|
-
workflow_jobs[name] =
|
|
392
|
+
workflow_jobs[name] = user_job
|
|
375
393
|
except ErtScriptLoadFailure as err:
|
|
376
394
|
ConfigWarning.warn(
|
|
377
|
-
f"Loading workflow job {
|
|
395
|
+
f"Loading workflow job {user_job_file!r}"
|
|
378
396
|
f" failed with '{err}'. It will not be loaded.",
|
|
379
|
-
|
|
397
|
+
user_job_file,
|
|
380
398
|
)
|
|
381
399
|
except ConfigValidationError as err:
|
|
382
|
-
errors.append(ErrorInfo(message=str(err)).set_context(
|
|
400
|
+
errors.append(ErrorInfo(message=str(err)).set_context(user_job_path))
|
|
383
401
|
if errors:
|
|
384
402
|
raise ConfigValidationError.from_collected(errors)
|
|
385
403
|
|
|
@@ -387,13 +405,11 @@ def workflow_jobs_from_dict(
|
|
|
387
405
|
|
|
388
406
|
|
|
389
407
|
def create_and_hook_workflows(
|
|
390
|
-
|
|
408
|
+
hook_workflow_info: list[tuple[str, HookRuntime]],
|
|
409
|
+
workflow_info: list[tuple[str, str]],
|
|
391
410
|
workflow_jobs: dict[str, WorkflowJob],
|
|
392
411
|
substitutions: dict[str, str],
|
|
393
412
|
) -> tuple[dict[str, Workflow], defaultdict[HookRuntime, list[Workflow]]]:
|
|
394
|
-
hook_workflow_info = content_dict.get(ConfigKeys.HOOK_WORKFLOW, [])
|
|
395
|
-
workflow_info = content_dict.get(ConfigKeys.LOAD_WORKFLOW, [])
|
|
396
|
-
|
|
397
413
|
workflows = {}
|
|
398
414
|
hooked_workflows = defaultdict(list)
|
|
399
415
|
|
|
@@ -411,7 +427,7 @@ def create_and_hook_workflows(
|
|
|
411
427
|
for job, args in workflow:
|
|
412
428
|
if isinstance(job, ErtScriptWorkflow):
|
|
413
429
|
try:
|
|
414
|
-
job.
|
|
430
|
+
job.load_ert_script_class().validate(args)
|
|
415
431
|
except ConfigValidationError as err:
|
|
416
432
|
errors.append(ErrorInfo(message=str(err)).set_context(work[0]))
|
|
417
433
|
continue
|
|
@@ -439,11 +455,11 @@ def create_and_hook_workflows(
|
|
|
439
455
|
wf = workflows[hook_name]
|
|
440
456
|
available_fixtures = fixtures_per_hook[mode]
|
|
441
457
|
for job, _ in wf.cmd_list:
|
|
442
|
-
if not
|
|
458
|
+
if not isinstance(job, BaseErtScriptWorkflow):
|
|
443
459
|
continue
|
|
444
460
|
|
|
445
|
-
|
|
446
|
-
ert_script_instance =
|
|
461
|
+
ert_script_class = job.load_ert_script_class()
|
|
462
|
+
ert_script_instance = ert_script_class()
|
|
447
463
|
requested_fixtures = ert_script_instance.requested_fixtures
|
|
448
464
|
|
|
449
465
|
# Look for requested fixtures that are not available for the given
|
|
@@ -485,7 +501,7 @@ def create_and_hook_workflows(
|
|
|
485
501
|
def workflows_from_dict(
|
|
486
502
|
content_dict: ConfigDict,
|
|
487
503
|
substitutions: dict[str, str],
|
|
488
|
-
|
|
504
|
+
site_installed_workflows_jobs: Mapping[str, WorkflowJob] | None = None,
|
|
489
505
|
) -> tuple[
|
|
490
506
|
dict[str, WorkflowJob],
|
|
491
507
|
dict[str, Workflow],
|
|
@@ -493,28 +509,31 @@ def workflows_from_dict(
|
|
|
493
509
|
]:
|
|
494
510
|
workflow_jobs = workflow_jobs_from_dict(
|
|
495
511
|
content_dict,
|
|
496
|
-
dict(copy.copy(
|
|
512
|
+
dict(copy.copy(site_installed_workflows_jobs))
|
|
513
|
+
if site_installed_workflows_jobs
|
|
514
|
+
else {},
|
|
497
515
|
)
|
|
498
516
|
workflows, hooked_workflows = create_and_hook_workflows(
|
|
499
|
-
content_dict,
|
|
517
|
+
content_dict.get(ConfigKeys.HOOK_WORKFLOW, []),
|
|
518
|
+
content_dict.get(ConfigKeys.LOAD_WORKFLOW, []),
|
|
519
|
+
workflow_jobs,
|
|
520
|
+
substitutions,
|
|
500
521
|
)
|
|
501
522
|
return workflow_jobs, workflows, hooked_workflows
|
|
502
523
|
|
|
503
524
|
|
|
504
525
|
def installed_forward_model_steps_from_dict(
|
|
505
526
|
config_dict: ConfigDict,
|
|
506
|
-
) -> dict[str,
|
|
527
|
+
) -> dict[str, UserInstalledForwardModelStep]:
|
|
507
528
|
errors: list[ErrorInfo | ConfigValidationError] = []
|
|
508
|
-
fm_steps: dict[str,
|
|
529
|
+
fm_steps: dict[str, UserInstalledForwardModelStep] = {}
|
|
509
530
|
for name, (fm_step_config_file, config_contents) in config_dict.get(
|
|
510
531
|
ConfigKeys.INSTALL_JOB, []
|
|
511
532
|
):
|
|
512
533
|
fm_step_config_file = path.abspath(fm_step_config_file)
|
|
513
534
|
try:
|
|
514
535
|
new_fm_step = forward_model_step_from_config_contents(
|
|
515
|
-
config_contents,
|
|
516
|
-
name=name,
|
|
517
|
-
config_file=fm_step_config_file,
|
|
536
|
+
config_contents, name=name, config_file=fm_step_config_file
|
|
518
537
|
)
|
|
519
538
|
except ConfigValidationError as e:
|
|
520
539
|
errors.append(e)
|
|
@@ -677,6 +696,8 @@ def log_observation_keys(
|
|
|
677
696
|
|
|
678
697
|
RESERVED_KEYWORDS = ["realization", "IENS", "ITER"]
|
|
679
698
|
|
|
699
|
+
USER_CONFIG_SCHEMA = init_user_config_schema()
|
|
700
|
+
|
|
680
701
|
|
|
681
702
|
class ErtConfig(BaseModel):
|
|
682
703
|
DEFAULT_ENSPATH: ClassVar[str] = "storage"
|
|
@@ -688,6 +709,7 @@ class ErtConfig(BaseModel):
|
|
|
688
709
|
QUEUE_OPTIONS: ClassVar[KnownQueueOptions | None] = None
|
|
689
710
|
RESERVED_KEYWORDS: ClassVar[list[str]] = RESERVED_KEYWORDS
|
|
690
711
|
ENV_VARS: ClassVar[dict[str, str]] = {}
|
|
712
|
+
PRIORITIZE_PRIVATE_IP_ADDRESS: ClassVar[bool] = False
|
|
691
713
|
|
|
692
714
|
substitutions: dict[str, str] = Field(default_factory=dict)
|
|
693
715
|
ensemble_config: EnsembleConfig = Field(default_factory=EnsembleConfig)
|
|
@@ -702,13 +724,11 @@ class ErtConfig(BaseModel):
|
|
|
702
724
|
default_factory=lambda: defaultdict(lambda: cast(list[Workflow], []))
|
|
703
725
|
)
|
|
704
726
|
runpath_file: Path = Path(DEFAULT_RUNPATH_FILE)
|
|
727
|
+
prioritize_private_ip_address: bool = False
|
|
705
728
|
|
|
706
729
|
ert_templates: list[tuple[str, str]] = Field(default_factory=list)
|
|
707
|
-
installed_forward_model_steps: dict[str, ForwardModelStep] = Field(
|
|
708
|
-
default_factory=dict
|
|
709
|
-
)
|
|
710
730
|
|
|
711
|
-
forward_model_steps: list[
|
|
731
|
+
forward_model_steps: list[SiteOrUserForwardModelStep] = Field(default_factory=list)
|
|
712
732
|
runpath_config: ModelConfig = Field(default_factory=ModelConfig)
|
|
713
733
|
user_config_file: str = "no_config"
|
|
714
734
|
config_path: str = Field(init=False, default="")
|
|
@@ -721,6 +741,18 @@ class ErtConfig(BaseModel):
|
|
|
721
741
|
@property
|
|
722
742
|
def observations(self) -> dict[str, pl.DataFrame]:
|
|
723
743
|
if self._observations is None:
|
|
744
|
+
has_rft_observations = any(
|
|
745
|
+
isinstance(o, RFTObservation) for o in self.observation_declarations
|
|
746
|
+
)
|
|
747
|
+
if (
|
|
748
|
+
has_rft_observations
|
|
749
|
+
and "rft" not in self.ensemble_config.response_configs
|
|
750
|
+
):
|
|
751
|
+
self.ensemble_config.response_configs["rft"] = RFTConfig(
|
|
752
|
+
input_files=[self.runpath_config.eclbase_format_string],
|
|
753
|
+
data_to_read={},
|
|
754
|
+
locations=[],
|
|
755
|
+
)
|
|
724
756
|
computed = create_observation_dataframes(
|
|
725
757
|
self.observation_declarations,
|
|
726
758
|
self.refcase,
|
|
@@ -728,6 +760,10 @@ class ErtConfig(BaseModel):
|
|
|
728
760
|
GenDataConfig | None,
|
|
729
761
|
self.ensemble_config.response_configs.get("gen_data", None),
|
|
730
762
|
),
|
|
763
|
+
cast(
|
|
764
|
+
RFTConfig | None,
|
|
765
|
+
self.ensemble_config.response_configs.get("rft", None),
|
|
766
|
+
),
|
|
731
767
|
self.time_map,
|
|
732
768
|
self.history_source,
|
|
733
769
|
)
|
|
@@ -779,6 +815,15 @@ class ErtConfig(BaseModel):
|
|
|
779
815
|
)
|
|
780
816
|
return self
|
|
781
817
|
|
|
818
|
+
@model_validator(mode="after")
|
|
819
|
+
def log_ensemble_config_contents(self) -> Self:
|
|
820
|
+
all_parameters = self.parameter_configurations_with_design_matrix
|
|
821
|
+
parameter_type_count = Counter(parameter.type for parameter in all_parameters)
|
|
822
|
+
logger.info(
|
|
823
|
+
f"EnsembleConfig contains parameters of type {dict(parameter_type_count)}"
|
|
824
|
+
)
|
|
825
|
+
return self
|
|
826
|
+
|
|
782
827
|
def __eq__(self, other: object) -> bool:
|
|
783
828
|
if not isinstance(other, ErtConfig):
|
|
784
829
|
return False
|
|
@@ -805,7 +850,7 @@ class ErtConfig(BaseModel):
|
|
|
805
850
|
def with_plugins(runtime_plugins: ErtRuntimePlugins) -> type[ErtConfig]:
|
|
806
851
|
class ErtConfigWithPlugins(ErtConfig):
|
|
807
852
|
PREINSTALLED_FORWARD_MODEL_STEPS: ClassVar[
|
|
808
|
-
Mapping[str,
|
|
853
|
+
Mapping[str, SiteInstalledForwardModelStep]
|
|
809
854
|
] = runtime_plugins.installed_forward_model_steps
|
|
810
855
|
PREINSTALLED_WORKFLOWS = dict(runtime_plugins.installed_workflow_jobs)
|
|
811
856
|
ENV_PR_FM_STEP: ClassVar[dict[str, dict[str, Any]]] = (
|
|
@@ -815,6 +860,9 @@ class ErtConfig(BaseModel):
|
|
|
815
860
|
)
|
|
816
861
|
ENV_VARS = dict(runtime_plugins.environment_variables)
|
|
817
862
|
QUEUE_OPTIONS = runtime_plugins.queue_options
|
|
863
|
+
PRIORITIZE_PRIVATE_IP_ADDRESS = (
|
|
864
|
+
runtime_plugins.prioritize_private_ip_address
|
|
865
|
+
)
|
|
818
866
|
|
|
819
867
|
ErtConfigWithPlugins.model_rebuild()
|
|
820
868
|
assert issubclass(ErtConfigWithPlugins, ErtConfig)
|
|
@@ -941,7 +989,9 @@ class ErtConfig(BaseModel):
|
|
|
941
989
|
errors.append(e)
|
|
942
990
|
|
|
943
991
|
try:
|
|
944
|
-
queue_config = QueueConfig.from_dict(
|
|
992
|
+
queue_config = QueueConfig.from_dict(
|
|
993
|
+
config_dict, site_queue_options=cls.QUEUE_OPTIONS
|
|
994
|
+
)
|
|
945
995
|
|
|
946
996
|
substitutions["<NUM_CPU>"] = str(queue_config.queue_options.num_cpu)
|
|
947
997
|
|
|
@@ -1011,11 +1061,30 @@ class ErtConfig(BaseModel):
|
|
|
1011
1061
|
if isinstance(cfg, GenKwConfig) and cfg.name in dm_params
|
|
1012
1062
|
]
|
|
1013
1063
|
if overwrite_params:
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1064
|
+
param_sampled = [
|
|
1065
|
+
k
|
|
1066
|
+
for k in overwrite_params
|
|
1067
|
+
if analysis_config.design_matrix.parameter_priority[k]
|
|
1068
|
+
== DataSource.SAMPLED
|
|
1069
|
+
]
|
|
1070
|
+
param_design = [
|
|
1071
|
+
k
|
|
1072
|
+
for k in overwrite_params
|
|
1073
|
+
if analysis_config.design_matrix.parameter_priority[k]
|
|
1074
|
+
== DataSource.DESIGN_MATRIX
|
|
1075
|
+
]
|
|
1076
|
+
if param_sampled:
|
|
1077
|
+
ConfigWarning.warn(
|
|
1078
|
+
f"Parameters {param_sampled} "
|
|
1079
|
+
"are also defined in design matrix, but due to the sampled"
|
|
1080
|
+
" priority they will remain as such."
|
|
1081
|
+
)
|
|
1082
|
+
if param_design:
|
|
1083
|
+
ConfigWarning.warn(
|
|
1084
|
+
f"Parameters {param_design} "
|
|
1085
|
+
"will be overridden by design matrix. This will cause "
|
|
1086
|
+
"updates to be turned off for these parameters."
|
|
1087
|
+
)
|
|
1019
1088
|
|
|
1020
1089
|
if dm_errors:
|
|
1021
1090
|
raise ConfigValidationError.from_collected(dm_errors)
|
|
@@ -1046,6 +1115,19 @@ class ErtConfig(BaseModel):
|
|
|
1046
1115
|
user_configured_.add(key)
|
|
1047
1116
|
env_vars[key] = substituter.substitute(val)
|
|
1048
1117
|
|
|
1118
|
+
prioritize_private_ip_address: bool = cls.PRIORITIZE_PRIVATE_IP_ADDRESS
|
|
1119
|
+
if ConfigKeys.PRIORITIZE_PRIVATE_IP_ADDRESS in config_dict:
|
|
1120
|
+
user_prioritize_private_ip_address = bool(
|
|
1121
|
+
config_dict[ConfigKeys.PRIORITIZE_PRIVATE_IP_ADDRESS]
|
|
1122
|
+
)
|
|
1123
|
+
if prioritize_private_ip_address != user_prioritize_private_ip_address:
|
|
1124
|
+
logger.warning(
|
|
1125
|
+
"PRIORITIZE_PRIVATE_IP_ADDRESS was overwritten by user: "
|
|
1126
|
+
f"{prioritize_private_ip_address} -> "
|
|
1127
|
+
f"{user_prioritize_private_ip_address}"
|
|
1128
|
+
)
|
|
1129
|
+
prioritize_private_ip_address = user_prioritize_private_ip_address
|
|
1130
|
+
|
|
1049
1131
|
try:
|
|
1050
1132
|
refcase = Refcase.from_config_dict(config_dict)
|
|
1051
1133
|
cls_config = cls(
|
|
@@ -1061,7 +1143,6 @@ class ErtConfig(BaseModel):
|
|
|
1061
1143
|
hooked_workflows=hooked_workflows,
|
|
1062
1144
|
runpath_file=Path(runpath_file),
|
|
1063
1145
|
ert_templates=read_templates(config_dict),
|
|
1064
|
-
installed_forward_model_steps=installed_forward_model_steps,
|
|
1065
1146
|
forward_model_steps=cls._create_list_of_forward_model_steps_to_run(
|
|
1066
1147
|
installed_forward_model_steps,
|
|
1067
1148
|
substitutions,
|
|
@@ -1073,11 +1154,21 @@ class ErtConfig(BaseModel):
|
|
|
1073
1154
|
time_map=time_map,
|
|
1074
1155
|
history_source=history_source,
|
|
1075
1156
|
refcase=refcase,
|
|
1157
|
+
prioritize_private_ip_address=prioritize_private_ip_address,
|
|
1076
1158
|
)
|
|
1077
1159
|
|
|
1078
1160
|
# The observations are created here because create_observation_dataframes
|
|
1079
1161
|
# will perform additonal validation which needs the context in
|
|
1080
1162
|
# obs_configs which is stripped by pydantic
|
|
1163
|
+
has_rft_observations = any(
|
|
1164
|
+
isinstance(o, RFTObservation) for o in obs_configs
|
|
1165
|
+
)
|
|
1166
|
+
if has_rft_observations and "rft" not in ensemble_config.response_configs:
|
|
1167
|
+
ensemble_config.response_configs["rft"] = RFTConfig(
|
|
1168
|
+
input_files=[eclbase],
|
|
1169
|
+
data_to_read={},
|
|
1170
|
+
locations=[],
|
|
1171
|
+
)
|
|
1081
1172
|
cls_config._observations = create_observation_dataframes(
|
|
1082
1173
|
obs_configs,
|
|
1083
1174
|
refcase,
|
|
@@ -1085,6 +1176,10 @@ class ErtConfig(BaseModel):
|
|
|
1085
1176
|
GenDataConfig | None,
|
|
1086
1177
|
ensemble_config.response_configs.get("gen_data", None),
|
|
1087
1178
|
),
|
|
1179
|
+
cast(
|
|
1180
|
+
RFTConfig | None,
|
|
1181
|
+
ensemble_config.response_configs.get("rft", None),
|
|
1182
|
+
),
|
|
1088
1183
|
time_map,
|
|
1089
1184
|
history_source,
|
|
1090
1185
|
)
|
|
@@ -1262,7 +1357,7 @@ class ErtConfig(BaseModel):
|
|
|
1262
1357
|
@classmethod
|
|
1263
1358
|
def _read_user_config_contents(cls, user_config: str, file_name: str) -> ConfigDict:
|
|
1264
1359
|
return parse_contents(
|
|
1265
|
-
user_config, file_name=file_name, schema=
|
|
1360
|
+
user_config, file_name=file_name, schema=USER_CONFIG_SCHEMA
|
|
1266
1361
|
)
|
|
1267
1362
|
|
|
1268
1363
|
@classmethod
|
|
@@ -1352,8 +1447,10 @@ def uppercase_subkeys_and_stringify_subvalues(
|
|
|
1352
1447
|
|
|
1353
1448
|
|
|
1354
1449
|
def forward_model_step_from_config_contents(
|
|
1355
|
-
config_contents: str,
|
|
1356
|
-
|
|
1450
|
+
config_contents: str,
|
|
1451
|
+
config_file: str,
|
|
1452
|
+
name: str | None = None,
|
|
1453
|
+
) -> UserInstalledForwardModelStep:
|
|
1357
1454
|
if name is None:
|
|
1358
1455
|
name = os.path.basename(config_file)
|
|
1359
1456
|
|
|
@@ -1377,7 +1474,7 @@ def forward_model_step_from_config_contents(
|
|
|
1377
1474
|
environment = {k: v for [k, v] in content_dict.get("ENV", [])}
|
|
1378
1475
|
default_mapping = {k: v for [k, v] in content_dict.get("DEFAULT", [])}
|
|
1379
1476
|
|
|
1380
|
-
return
|
|
1477
|
+
return UserInstalledForwardModelStep(
|
|
1381
1478
|
name=name,
|
|
1382
1479
|
executable=content_dict["EXECUTABLE"],
|
|
1383
1480
|
stdin_file=content_dict.get("STDIN"),
|