ert 17.1.7__py3-none-any.whl → 18.0.0__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/__main__.py +8 -7
- ert/analysis/_enif_update.py +8 -4
- ert/analysis/_update_commons.py +16 -6
- ert/cli/main.py +6 -3
- ert/cli/monitor.py +7 -0
- ert/config/__init__.py +13 -3
- ert/config/_create_observation_dataframes.py +60 -12
- ert/config/_observations.py +14 -1
- ert/config/_read_summary.py +8 -6
- ert/config/ensemble_config.py +6 -14
- ert/config/ert_config.py +19 -13
- ert/config/{everest_objective_config.py → everest_response.py} +23 -12
- ert/config/ext_param_config.py +133 -1
- ert/config/field.py +12 -8
- ert/config/forward_model_step.py +108 -6
- ert/config/gen_data_config.py +2 -6
- ert/config/gen_kw_config.py +0 -9
- ert/config/known_response_types.py +14 -0
- ert/config/parameter_config.py +0 -17
- ert/config/parsing/config_keywords.py +1 -0
- ert/config/parsing/config_schema.py +12 -0
- ert/config/parsing/config_schema_deprecations.py +11 -0
- ert/config/parsing/config_schema_item.py +1 -1
- ert/config/queue_config.py +4 -4
- ert/config/response_config.py +0 -7
- ert/config/rft_config.py +230 -0
- ert/config/summary_config.py +2 -6
- ert/config/violations.py +0 -0
- ert/config/workflow_fixtures.py +2 -1
- 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/compute/misfits.py +7 -6
- ert/dark_storage/endpoints/compute/misfits.py +2 -2
- ert/dark_storage/endpoints/observations.py +4 -4
- ert/dark_storage/endpoints/responses.py +15 -1
- ert/ensemble_evaluator/__init__.py +8 -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 +211 -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/create_experiment_dialog.py +3 -1
- ert/gui/ertwidgets/ensembleselector.py +2 -2
- ert/gui/ertwidgets/models/__init__.py +2 -0
- ert/gui/ertwidgets/models/activerealizationsmodel.py +2 -1
- ert/gui/ertwidgets/models/path_model.py +1 -1
- ert/gui/ertwidgets/models/targetensemblemodel.py +2 -1
- ert/gui/ertwidgets/models/text_model.py +1 -1
- ert/gui/ertwidgets/searchbox.py +13 -4
- ert/gui/{suggestor → ertwidgets/suggestor}/_suggestor_message.py +13 -4
- ert/gui/main.py +11 -6
- ert/gui/main_window.py +1 -2
- ert/gui/simulation/ensemble_experiment_panel.py +1 -1
- ert/gui/simulation/ensemble_information_filter_panel.py +1 -1
- ert/gui/simulation/ensemble_smoother_panel.py +1 -1
- ert/gui/simulation/evaluate_ensemble_panel.py +1 -1
- ert/gui/simulation/experiment_panel.py +1 -1
- ert/gui/simulation/manual_update_panel.py +31 -8
- ert/gui/simulation/multiple_data_assimilation_panel.py +12 -8
- ert/gui/simulation/run_dialog.py +25 -4
- ert/gui/simulation/single_test_run_panel.py +2 -2
- ert/gui/summarypanel.py +1 -1
- ert/gui/tools/load_results/load_results_panel.py +1 -1
- ert/gui/tools/manage_experiments/storage_info_widget.py +7 -7
- ert/gui/tools/manage_experiments/storage_widget.py +1 -2
- ert/gui/tools/plot/plot_api.py +13 -10
- ert/gui/tools/plot/plot_window.py +12 -0
- 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/ensemble.py +9 -2
- ert/gui/tools/plot/plottery/plots/statistics.py +59 -19
- ert/mode_definitions.py +2 -0
- ert/plugins/__init__.py +0 -1
- ert/plugins/hook_implementations/workflows/gen_data_rft_export.py +10 -2
- ert/plugins/hook_specifications/__init__.py +0 -2
- ert/plugins/hook_specifications/jobs.py +0 -9
- ert/plugins/plugin_manager.py +2 -33
- ert/resources/shell_scripts/delete_directory.py +2 -2
- ert/run_models/__init__.py +18 -5
- ert/run_models/_create_run_path.py +56 -23
- 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 +155 -44
- ert/run_models/initial_ensemble_run_model.py +23 -22
- ert/run_models/manual_update.py +4 -2
- ert/run_models/manual_update_enif.py +37 -0
- ert/run_models/model_factory.py +81 -22
- ert/run_models/multiple_data_assimilation.py +21 -10
- ert/run_models/run_model.py +54 -34
- 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/driver.py +37 -0
- ert/scheduler/event.py +3 -1
- ert/scheduler/job.py +23 -13
- ert/scheduler/lsf_driver.py +6 -2
- ert/scheduler/openpbs_driver.py +7 -1
- ert/scheduler/scheduler.py +5 -0
- ert/scheduler/slurm_driver.py +6 -2
- ert/services/__init__.py +2 -2
- ert/services/_base_service.py +31 -15
- ert/services/ert_server.py +317 -0
- ert/shared/_doc_utils/ert_jobs.py +1 -4
- ert/shared/storage/connection.py +3 -3
- ert/shared/version.py +3 -3
- ert/storage/local_ensemble.py +25 -5
- ert/storage/local_experiment.py +6 -14
- ert/storage/local_storage.py +35 -30
- ert/storage/migration/to18.py +12 -0
- ert/storage/migration/to8.py +4 -4
- ert/substitutions.py +12 -28
- ert/validation/active_range.py +7 -7
- ert/validation/rangestring.py +16 -16
- {ert-17.1.7.dist-info → ert-18.0.0.dist-info}/METADATA +8 -7
- {ert-17.1.7.dist-info → ert-18.0.0.dist-info}/RECORD +160 -159
- everest/bin/config_branch_script.py +3 -6
- everest/bin/everconfigdump_script.py +1 -9
- everest/bin/everest_script.py +21 -11
- everest/bin/kill_script.py +2 -2
- everest/bin/monitor_script.py +2 -2
- everest/bin/utils.py +6 -3
- everest/config/__init__.py +4 -1
- everest/config/control_config.py +61 -2
- everest/config/control_variable_config.py +2 -1
- everest/config/everest_config.py +38 -16
- everest/config/forward_model_config.py +5 -3
- everest/config/install_data_config.py +7 -5
- everest/config/install_job_config.py +7 -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 -49
- everest/config/utils.py +25 -105
- everest/config/validation_utils.py +10 -10
- everest/config_file_loader.py +13 -2
- everest/detached/everserver.py +7 -8
- everest/everest_storage.py +6 -10
- everest/gui/everest_client.py +0 -1
- everest/gui/main_window.py +2 -2
- everest/optimizer/everest2ropt.py +59 -32
- everest/optimizer/opt_model_transforms.py +12 -13
- everest/optimizer/utils.py +0 -29
- everest/strings.py +0 -5
- ert/config/everest_constraints_config.py +0 -95
- ert/services/storage_service.py +0 -127
- everest/config/sampler_config.py +0 -103
- everest/simulator/__init__.py +0 -88
- everest/simulator/everest_to_ert.py +0 -51
- /ert/gui/{suggestor → ertwidgets/suggestor}/__init__.py +0 -0
- /ert/gui/{suggestor → ertwidgets/suggestor}/_colors.py +0 -0
- /ert/gui/{suggestor → ertwidgets/suggestor}/suggestor.py +0 -0
- {ert-17.1.7.dist-info → ert-18.0.0.dist-info}/WHEEL +0 -0
- {ert-17.1.7.dist-info → ert-18.0.0.dist-info}/entry_points.txt +0 -0
- {ert-17.1.7.dist-info → ert-18.0.0.dist-info}/licenses/COPYING +0 -0
- {ert-17.1.7.dist-info → ert-18.0.0.dist-info}/top_level.txt +0 -0
|
@@ -3,9 +3,9 @@ from dataclasses import dataclass
|
|
|
3
3
|
from typing import cast
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
|
-
from PyQt6.QtCore import
|
|
6
|
+
from PyQt6.QtCore import pyqtSignal
|
|
7
7
|
from PyQt6.QtCore import pyqtSlot as Slot
|
|
8
|
-
from PyQt6.QtWidgets import QFormLayout, QLabel, QWidget
|
|
8
|
+
from PyQt6.QtWidgets import QComboBox, QFormLayout, QLabel, QWidget
|
|
9
9
|
from typing_extensions import override
|
|
10
10
|
|
|
11
11
|
from ert.config import AnalysisConfig, ErrorInfo
|
|
@@ -16,11 +16,11 @@ from ert.gui.ertwidgets import (
|
|
|
16
16
|
CopyableLabel,
|
|
17
17
|
EnsembleSelector,
|
|
18
18
|
StringBox,
|
|
19
|
+
Suggestor,
|
|
19
20
|
TargetEnsembleModel,
|
|
20
21
|
)
|
|
21
22
|
from ert.gui.simulation.experiment_config_panel import ExperimentConfigPanel
|
|
22
|
-
from ert.
|
|
23
|
-
from ert.mode_definitions import MANUAL_UPDATE_MODE
|
|
23
|
+
from ert.mode_definitions import MANUAL_ENIF_UPDATE_MODE, MANUAL_UPDATE_MODE
|
|
24
24
|
from ert.run_models.manual_update import ManualUpdate
|
|
25
25
|
from ert.storage import Ensemble, RealizationStorageState
|
|
26
26
|
from ert.validation import EnsembleRealizationsArgument, ProperNameFormatArgument
|
|
@@ -38,6 +38,8 @@ class Arguments:
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class ManualUpdatePanel(ExperimentConfigPanel):
|
|
41
|
+
updateMethodChanged = pyqtSignal(str)
|
|
42
|
+
|
|
41
43
|
def __init__(
|
|
42
44
|
self,
|
|
43
45
|
run_path: str,
|
|
@@ -49,9 +51,17 @@ class ManualUpdatePanel(ExperimentConfigPanel):
|
|
|
49
51
|
self.setObjectName("Manual_update_panel")
|
|
50
52
|
|
|
51
53
|
layout = QFormLayout()
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
self._update_method_dropdown = QComboBox()
|
|
55
|
+
self._update_method_dropdown.addItems(
|
|
56
|
+
["ES Update", "EnIF Update (Experimental)"]
|
|
57
|
+
)
|
|
58
|
+
self._update_method_dropdown.currentTextChanged.connect(
|
|
59
|
+
self._on_update_method_changed
|
|
60
|
+
)
|
|
61
|
+
self._update_method_dropdown.setObjectName("manual_update_method_dropdown")
|
|
62
|
+
|
|
63
|
+
layout.addRow("Update method:", self._update_method_dropdown)
|
|
64
|
+
|
|
55
65
|
self._ensemble_selector = EnsembleSelector(
|
|
56
66
|
notifier, show_only_with_response_data=True
|
|
57
67
|
)
|
|
@@ -97,6 +107,17 @@ class ManualUpdatePanel(ExperimentConfigPanel):
|
|
|
97
107
|
self._ensemble_selector.currentIndexChanged.connect(self._realizations_from_fs)
|
|
98
108
|
self.setLayout(layout)
|
|
99
109
|
|
|
110
|
+
@property
|
|
111
|
+
def selected_update_method(self) -> str:
|
|
112
|
+
return self._update_method_dropdown.currentText()
|
|
113
|
+
|
|
114
|
+
@Slot(str)
|
|
115
|
+
def _on_update_method_changed(self, new_method: str) -> None:
|
|
116
|
+
if new_method == "ES Update":
|
|
117
|
+
self._analysis_module_edit.show()
|
|
118
|
+
else:
|
|
119
|
+
self._analysis_module_edit.hide()
|
|
120
|
+
|
|
100
121
|
@override
|
|
101
122
|
def isConfigurationValid(self) -> bool:
|
|
102
123
|
return (
|
|
@@ -107,7 +128,9 @@ class ManualUpdatePanel(ExperimentConfigPanel):
|
|
|
107
128
|
@override
|
|
108
129
|
def get_experiment_arguments(self) -> Arguments:
|
|
109
130
|
return Arguments(
|
|
110
|
-
mode=MANUAL_UPDATE_MODE
|
|
131
|
+
mode=MANUAL_UPDATE_MODE
|
|
132
|
+
if self.selected_update_method == "ES Update"
|
|
133
|
+
else MANUAL_ENIF_UPDATE_MODE,
|
|
111
134
|
ensemble_id=str(
|
|
112
135
|
cast(Ensemble, self._ensemble_selector.selected_ensemble).id
|
|
113
136
|
),
|
|
@@ -18,14 +18,14 @@ from ert.gui.ertwidgets import (
|
|
|
18
18
|
CopyableLabel,
|
|
19
19
|
EnsembleSelector,
|
|
20
20
|
StringBox,
|
|
21
|
+
Suggestor,
|
|
21
22
|
TargetEnsembleModel,
|
|
22
23
|
TextModel,
|
|
23
24
|
ValueModel,
|
|
25
|
+
get_parameters_button,
|
|
24
26
|
)
|
|
25
|
-
from ert.gui.ertwidgets.parameterviewer import get_parameters_button
|
|
26
|
-
from ert.gui.suggestor import Suggestor
|
|
27
27
|
from ert.mode_definitions import ES_MDA_MODE
|
|
28
|
-
from ert.run_models import MultipleDataAssimilation
|
|
28
|
+
from ert.run_models import MultipleDataAssimilation, MultipleDataAssimilationConfig
|
|
29
29
|
from ert.storage.realization_storage_state import RealizationStorageState
|
|
30
30
|
from ert.validation import (
|
|
31
31
|
ExperimentValidation,
|
|
@@ -114,7 +114,7 @@ class MultipleDataAssimilationPanel(ExperimentConfigPanel):
|
|
|
114
114
|
self._target_ensemble_format_field.setValidator(ProperNameFormatArgument())
|
|
115
115
|
layout.addRow("Target ensemble format:", self._target_ensemble_format_field)
|
|
116
116
|
|
|
117
|
-
self.weights =
|
|
117
|
+
self.weights = MultipleDataAssimilationConfig.default_weights
|
|
118
118
|
self.weights_valid = True
|
|
119
119
|
self._createInputForWeights(layout)
|
|
120
120
|
|
|
@@ -135,6 +135,8 @@ class MultipleDataAssimilationPanel(ExperimentConfigPanel):
|
|
|
135
135
|
self._active_realizations_field.model.setValueFromMask( # type: ignore
|
|
136
136
|
active_realizations
|
|
137
137
|
)
|
|
138
|
+
self._initial_active_realizations = active_realizations
|
|
139
|
+
|
|
138
140
|
self._ensemble_selector = EnsembleSelector(notifier)
|
|
139
141
|
self._previous_ensemble_realizations_validator = EnsembleRealizationsArgument(
|
|
140
142
|
lambda: self._ensemble_selector.selected_ensemble,
|
|
@@ -215,7 +217,7 @@ class MultipleDataAssimilationPanel(ExperimentConfigPanel):
|
|
|
215
217
|
|
|
216
218
|
self._relative_iteration_weights_box.setText(
|
|
217
219
|
self._ensemble_selector.selected_ensemble.relative_weights
|
|
218
|
-
or
|
|
220
|
+
or MultipleDataAssimilationConfig.default_weights
|
|
219
221
|
)
|
|
220
222
|
self._evaluate_weights_box_enabled()
|
|
221
223
|
|
|
@@ -250,9 +252,9 @@ class MultipleDataAssimilationPanel(ExperimentConfigPanel):
|
|
|
250
252
|
self._ensemble_selector.selected_ensemble is not None
|
|
251
253
|
and self._ensemble_selector.selected_ensemble.relative_weights
|
|
252
254
|
)
|
|
253
|
-
or
|
|
255
|
+
or MultipleDataAssimilationConfig.default_weights
|
|
254
256
|
if self._restart_box.isChecked()
|
|
255
|
-
else
|
|
257
|
+
else MultipleDataAssimilationConfig.default_weights
|
|
256
258
|
)
|
|
257
259
|
if self._restart_box.isChecked():
|
|
258
260
|
self._active_realizations_field.setValidator(
|
|
@@ -264,7 +266,9 @@ class MultipleDataAssimilationPanel(ExperimentConfigPanel):
|
|
|
264
266
|
self._active_realizations_field.setValidator(
|
|
265
267
|
self._new_ensemble_realizations_validator
|
|
266
268
|
)
|
|
267
|
-
self._active_realizations_field.model.
|
|
269
|
+
self._active_realizations_field.model.setValueFromMask( # type: ignore
|
|
270
|
+
self._initial_active_realizations
|
|
271
|
+
)
|
|
268
272
|
|
|
269
273
|
def _createInputForWeights(self, layout: QFormLayout) -> None:
|
|
270
274
|
relative_iteration_weights_model = ValueModel(self.weights)
|
ert/gui/simulation/run_dialog.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
from datetime import datetime
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from queue import SimpleQueue
|
|
6
7
|
from typing import assert_never, cast
|
|
@@ -30,15 +31,18 @@ from PyQt6.QtWidgets import (
|
|
|
30
31
|
)
|
|
31
32
|
from typing_extensions import override
|
|
32
33
|
|
|
34
|
+
from _ert.events import EnsembleEvaluationWarning
|
|
33
35
|
from ert.config import ErrorInfo, QueueSystem, WarningInfo
|
|
34
36
|
from ert.ensemble_evaluator import (
|
|
35
37
|
EndEvent,
|
|
36
38
|
FullSnapshotEvent,
|
|
37
39
|
SnapshotUpdateEvent,
|
|
40
|
+
StartEvent,
|
|
38
41
|
WarningEvent,
|
|
39
42
|
)
|
|
40
43
|
from ert.ensemble_evaluator import identifiers as ids
|
|
41
44
|
from ert.gui.ertnotifier import ErtNotifier
|
|
45
|
+
from ert.gui.ertwidgets import Suggestor
|
|
42
46
|
from ert.gui.model.fm_step_list import FMStepListProxyModel
|
|
43
47
|
from ert.gui.model.node import IterNode
|
|
44
48
|
from ert.gui.model.real_list import RealListModel
|
|
@@ -49,7 +53,6 @@ from ert.gui.model.snapshot import (
|
|
|
49
53
|
RealIens,
|
|
50
54
|
SnapshotModel,
|
|
51
55
|
)
|
|
52
|
-
from ert.gui.suggestor import Suggestor
|
|
53
56
|
from ert.gui.tools.file import FileDialog
|
|
54
57
|
from ert.run_models import (
|
|
55
58
|
RunModelAPI,
|
|
@@ -258,6 +261,7 @@ class RunDialog(QFrame):
|
|
|
258
261
|
self._fm_step_label.setObjectName("fm_step_label")
|
|
259
262
|
self._fm_step_overview = FMStepOverview(self._snapshot_model, self)
|
|
260
263
|
|
|
264
|
+
self._start_time: datetime | None = None
|
|
261
265
|
self.running_time = QLabel("Running time:\n -")
|
|
262
266
|
self.running_time.setMinimumWidth(150)
|
|
263
267
|
self.queue_system = QLabel("")
|
|
@@ -524,9 +528,11 @@ class RunDialog(QFrame):
|
|
|
524
528
|
|
|
525
529
|
@Slot()
|
|
526
530
|
def _on_ticker(self) -> None:
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
531
|
+
if self._start_time:
|
|
532
|
+
humanized_runtime = humanize.precisedelta(
|
|
533
|
+
datetime.now() - self._start_time, minimum_unit="seconds", format="%d"
|
|
534
|
+
)
|
|
535
|
+
self.running_time.setText(f"Running time:\n{humanized_runtime}")
|
|
530
536
|
|
|
531
537
|
maximum_memory_usage = self._snapshot_model.root.max_memory_usage
|
|
532
538
|
|
|
@@ -543,11 +549,16 @@ class RunDialog(QFrame):
|
|
|
543
549
|
def _on_event(self, event: object) -> None:
|
|
544
550
|
model = self._snapshot_model
|
|
545
551
|
match event:
|
|
552
|
+
case StartEvent():
|
|
553
|
+
self._start_time = event.timestamp
|
|
546
554
|
case EndEvent(failed=failed, msg=msg):
|
|
547
555
|
self.simulation_done.emit(failed, msg)
|
|
548
556
|
self._ticker.stop()
|
|
549
557
|
case WarningEvent(msg=msg):
|
|
550
558
|
self.post_simulation_warnings.append(msg)
|
|
559
|
+
case EnsembleEvaluationWarning(warning_message=msg):
|
|
560
|
+
self._show_warning(msg)
|
|
561
|
+
|
|
551
562
|
case FullSnapshotEvent(
|
|
552
563
|
status_count=status_count, realization_count=realization_count
|
|
553
564
|
):
|
|
@@ -650,6 +661,7 @@ class RunDialog(QFrame):
|
|
|
650
661
|
if result == QMessageBox.StandardButton.Ok:
|
|
651
662
|
self.rerun_button.setEnabled(False)
|
|
652
663
|
self.kill_button.setEnabled(True)
|
|
664
|
+
self.post_simulation_warnings.clear()
|
|
653
665
|
self._is_rerunning_failed_realizations = True
|
|
654
666
|
self.rerun_failed_realizations_experiment.emit()
|
|
655
667
|
self.set_show_warning_button_to_initial_state()
|
|
@@ -673,6 +685,15 @@ class RunDialog(QFrame):
|
|
|
673
685
|
for file_dialog in self.findChildren(FileDialog):
|
|
674
686
|
file_dialog.close()
|
|
675
687
|
|
|
688
|
+
def _show_warning(self, msg: str) -> None:
|
|
689
|
+
msg_box = QMessageBox(self)
|
|
690
|
+
msg_box.setObjectName("EnsembleEvaluationWarningBox")
|
|
691
|
+
msg_box.setIcon(QMessageBox.Icon.Warning)
|
|
692
|
+
msg_box.setWindowTitle("Ensemble Evaluation Warning")
|
|
693
|
+
msg_box.setText(msg)
|
|
694
|
+
msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
|
|
695
|
+
msg_box.show()
|
|
696
|
+
|
|
676
697
|
|
|
677
698
|
# Cannot use a non-static method here as
|
|
678
699
|
# it is called when the object is destroyed
|
|
@@ -4,13 +4,13 @@ from PyQt6.QtCore import Qt
|
|
|
4
4
|
from PyQt6.QtWidgets import QFormLayout, QLabel
|
|
5
5
|
from typing_extensions import override
|
|
6
6
|
|
|
7
|
+
from ert.config import AnalysisConfig, ParameterConfig
|
|
7
8
|
from ert.gui.ertnotifier import ErtNotifier
|
|
8
9
|
from ert.gui.ertwidgets import CopyableLabel
|
|
9
10
|
from ert.mode_definitions import TEST_RUN_MODE
|
|
10
11
|
from ert.run_models import SingleTestRun
|
|
11
12
|
|
|
12
|
-
from
|
|
13
|
-
from ..ertwidgets.parameterviewer import get_parameters_button
|
|
13
|
+
from ..ertwidgets import get_parameters_button
|
|
14
14
|
from ._design_matrix_panel import DesignMatrixPanel
|
|
15
15
|
from .experiment_config_panel import ExperimentConfigPanel
|
|
16
16
|
|
ert/gui/summarypanel.py
CHANGED
|
@@ -13,10 +13,10 @@ from ert.gui.ertwidgets import (
|
|
|
13
13
|
EnsembleSelector,
|
|
14
14
|
QApplication,
|
|
15
15
|
StringBox,
|
|
16
|
+
Suggestor,
|
|
16
17
|
TextBox,
|
|
17
18
|
TextModel,
|
|
18
19
|
)
|
|
19
|
-
from ert.gui.suggestor import Suggestor
|
|
20
20
|
from ert.run_models.run_model import captured_logs
|
|
21
21
|
from ert.storage.local_ensemble import load_parameters_and_responses_from_runpath
|
|
22
22
|
from ert.validation import RangeStringArgument, StringDefinition
|
|
@@ -189,9 +189,9 @@ class _EnsembleWidget(QWidget):
|
|
|
189
189
|
|
|
190
190
|
response_type, obs_for_type = next(
|
|
191
191
|
(
|
|
192
|
-
(response_type,
|
|
193
|
-
for response_type,
|
|
194
|
-
if observation_key in
|
|
192
|
+
(response_type, df)
|
|
193
|
+
for response_type, df in observations_dict.items()
|
|
194
|
+
if observation_key in df["observation_key"]
|
|
195
195
|
),
|
|
196
196
|
(None, None),
|
|
197
197
|
)
|
|
@@ -418,14 +418,14 @@ class _RealizationWidget(QWidget):
|
|
|
418
418
|
)
|
|
419
419
|
|
|
420
420
|
html = "<table>"
|
|
421
|
-
for name,
|
|
422
|
-
html += f"<tr><td>{name} - {
|
|
421
|
+
for name, response_state in ensemble.get_response_state(realization).items():
|
|
422
|
+
html += f"<tr><td>{name} - {response_state.name}</td></tr>"
|
|
423
423
|
html += "</table>"
|
|
424
424
|
self._response_text_edit.setHtml(html)
|
|
425
425
|
|
|
426
426
|
html = "<table>"
|
|
427
|
-
for name,
|
|
428
|
-
html += f"<tr><td>{name} - {
|
|
427
|
+
for name, param_state in ensemble.get_parameter_state(realization).items():
|
|
428
|
+
html += f"<tr><td>{name} - {param_state.name}</td></tr>"
|
|
429
429
|
html += "</table>"
|
|
430
430
|
self._parameter_text_edit.setHtml(html)
|
|
431
431
|
|
|
@@ -24,8 +24,7 @@ from PyQt6.QtWidgets import (
|
|
|
24
24
|
|
|
25
25
|
from ert.config import ErrorInfo, ErtConfig
|
|
26
26
|
from ert.gui.ertnotifier import ErtNotifier
|
|
27
|
-
from ert.gui.ertwidgets
|
|
28
|
-
from ert.gui.suggestor import Suggestor
|
|
27
|
+
from ert.gui.ertwidgets import CreateExperimentDialog, Suggestor
|
|
29
28
|
from ert.storage import Ensemble, Experiment
|
|
30
29
|
|
|
31
30
|
from .storage_model import (
|
ert/gui/tools/plot/plot_api.py
CHANGED
|
@@ -19,7 +19,7 @@ from pandas.errors import ParserError
|
|
|
19
19
|
from resfo_utilities import history_key
|
|
20
20
|
|
|
21
21
|
from ert.config import ParameterMetadata, ResponseMetadata
|
|
22
|
-
from ert.services import
|
|
22
|
+
from ert.services import ErtServer
|
|
23
23
|
from ert.storage.realization_storage_state import RealizationStorageState
|
|
24
24
|
|
|
25
25
|
logger = logging.getLogger(__name__)
|
|
@@ -56,7 +56,7 @@ class PlotApi:
|
|
|
56
56
|
|
|
57
57
|
@property
|
|
58
58
|
def api_version(self) -> str:
|
|
59
|
-
with
|
|
59
|
+
with ErtServer.session(project=self.ens_path) as client:
|
|
60
60
|
try:
|
|
61
61
|
response = client.get("/version", timeout=self._timeout)
|
|
62
62
|
self._check_response(response)
|
|
@@ -82,7 +82,7 @@ class PlotApi:
|
|
|
82
82
|
return self._all_ensembles
|
|
83
83
|
|
|
84
84
|
self._all_ensembles = []
|
|
85
|
-
with
|
|
85
|
+
with ErtServer.session(project=self.ens_path) as client:
|
|
86
86
|
try:
|
|
87
87
|
response = client.get("/experiments", timeout=self._timeout)
|
|
88
88
|
self._check_response(response)
|
|
@@ -138,7 +138,7 @@ class PlotApi:
|
|
|
138
138
|
all_keys: dict[str, PlotApiKeyDefinition] = {}
|
|
139
139
|
all_params = {}
|
|
140
140
|
|
|
141
|
-
with
|
|
141
|
+
with ErtServer.session(project=self.ens_path) as client:
|
|
142
142
|
response = client.get("/experiments", timeout=self._timeout)
|
|
143
143
|
self._check_response(response)
|
|
144
144
|
|
|
@@ -162,7 +162,7 @@ class PlotApi:
|
|
|
162
162
|
def responses_api_key_defs(self) -> list[PlotApiKeyDefinition]:
|
|
163
163
|
key_defs: dict[str, PlotApiKeyDefinition] = {}
|
|
164
164
|
|
|
165
|
-
with
|
|
165
|
+
with ErtServer.session(project=self.ens_path) as client:
|
|
166
166
|
response = client.get("/experiments", timeout=self._timeout)
|
|
167
167
|
self._check_response(response)
|
|
168
168
|
|
|
@@ -224,7 +224,7 @@ class PlotApi:
|
|
|
224
224
|
response_key: str,
|
|
225
225
|
filter_on: dict[str, Any] | None = None,
|
|
226
226
|
) -> pd.DataFrame:
|
|
227
|
-
with
|
|
227
|
+
with ErtServer.session(project=self.ens_path) as client:
|
|
228
228
|
response = client.get(
|
|
229
229
|
f"/ensembles/{ensemble_id}/responses/{PlotApi.escape(response_key)}",
|
|
230
230
|
headers={"accept": "application/x-parquet"},
|
|
@@ -241,7 +241,10 @@ class PlotApi:
|
|
|
241
241
|
try:
|
|
242
242
|
df.columns = pd.to_datetime(df.columns, format="%Y-%m-%d %H:%M:%S")
|
|
243
243
|
except (ParserError, ValueError):
|
|
244
|
-
|
|
244
|
+
try:
|
|
245
|
+
df.columns = [int(s) for s in df.columns]
|
|
246
|
+
except ValueError:
|
|
247
|
+
df.columns = [float(s) for s in df.columns]
|
|
245
248
|
|
|
246
249
|
try:
|
|
247
250
|
return df.astype(float)
|
|
@@ -249,7 +252,7 @@ class PlotApi:
|
|
|
249
252
|
return df
|
|
250
253
|
|
|
251
254
|
def data_for_parameter(self, ensemble_id: str, parameter_key: str) -> pd.DataFrame:
|
|
252
|
-
with
|
|
255
|
+
with ErtServer.session(project=self.ens_path) as client:
|
|
253
256
|
parameter = client.get(
|
|
254
257
|
f"/ensembles/{ensemble_id}/parameters/{PlotApi.escape(parameter_key)}",
|
|
255
258
|
headers={"accept": "application/x-parquet"},
|
|
@@ -291,7 +294,7 @@ class PlotApi:
|
|
|
291
294
|
assert key_def.response_metadata is not None
|
|
292
295
|
actual_response_key = key_def.response_metadata.response_key
|
|
293
296
|
filter_on = key_def.filter_on
|
|
294
|
-
with
|
|
297
|
+
with ErtServer.session(project=self.ens_path) as client:
|
|
295
298
|
response = client.get(
|
|
296
299
|
f"/ensembles/{ensemble.id}/responses/{PlotApi.escape(actual_response_key)}/observations",
|
|
297
300
|
timeout=self._timeout,
|
|
@@ -374,7 +377,7 @@ class PlotApi:
|
|
|
374
377
|
if not ensemble:
|
|
375
378
|
return np.array([])
|
|
376
379
|
|
|
377
|
-
with
|
|
380
|
+
with ErtServer.session(project=self.ens_path) as client:
|
|
378
381
|
response = client.get(
|
|
379
382
|
f"/ensembles/{ensemble.id}/parameters/{PlotApi.escape(key)}/std_dev",
|
|
380
383
|
params={"z": z},
|
|
@@ -335,6 +335,18 @@ class PlotWindow(QMainWindow):
|
|
|
335
335
|
handle_exception(e)
|
|
336
336
|
plot_context.history_data = None
|
|
337
337
|
|
|
338
|
+
if (
|
|
339
|
+
key_def.response_metadata is not None
|
|
340
|
+
and key_def.response_metadata.response_type == "rft"
|
|
341
|
+
):
|
|
342
|
+
plot_context.setXLabel(key.split(":")[-1])
|
|
343
|
+
plot_context.setYLabel("TVD")
|
|
344
|
+
plot_context.depth_y_axis = True
|
|
345
|
+
for ekey, data in list(ensemble_to_data_map.items()):
|
|
346
|
+
ensemble_to_data_map[ekey] = data.interpolate(
|
|
347
|
+
method="linear", axis="columns"
|
|
348
|
+
)
|
|
349
|
+
|
|
338
350
|
for data in ensemble_to_data_map.values():
|
|
339
351
|
data = data.T
|
|
340
352
|
|
|
@@ -47,6 +47,14 @@ class PlotContext:
|
|
|
47
47
|
self._y_axis: str | None = None
|
|
48
48
|
self._log_scale = False
|
|
49
49
|
|
|
50
|
+
@property
|
|
51
|
+
def depth_y_axis(self) -> bool:
|
|
52
|
+
return self._plot_config.depth_y_axis
|
|
53
|
+
|
|
54
|
+
@depth_y_axis.setter
|
|
55
|
+
def depth_y_axis(self, value: bool) -> None:
|
|
56
|
+
self._plot_config.depth_y_axis = value
|
|
57
|
+
|
|
50
58
|
def plotConfig(self) -> PlotConfig:
|
|
51
59
|
return self._plot_config
|
|
52
60
|
|
|
@@ -93,6 +101,12 @@ class PlotContext:
|
|
|
93
101
|
)
|
|
94
102
|
self._y_axis = value
|
|
95
103
|
|
|
104
|
+
def setXLabel(self, value: str) -> None:
|
|
105
|
+
self._plot_config.setXLabel(value)
|
|
106
|
+
|
|
107
|
+
def setYLabel(self, value: str) -> None:
|
|
108
|
+
self._plot_config.setYLabel(value)
|
|
109
|
+
|
|
96
110
|
@property
|
|
97
111
|
def log_scale(self) -> bool:
|
|
98
112
|
return self._log_scale
|
|
@@ -86,9 +86,16 @@ class EnsemblePlot:
|
|
|
86
86
|
if len(data) == 1 and not style.marker:
|
|
87
87
|
style.marker = "."
|
|
88
88
|
|
|
89
|
+
if plot_config.depth_y_axis:
|
|
90
|
+
x = data.to_numpy()
|
|
91
|
+
y = data.index.to_numpy()
|
|
92
|
+
axes.yaxis.set_inverted(True)
|
|
93
|
+
else:
|
|
94
|
+
y = data.to_numpy()
|
|
95
|
+
x = data.index.to_numpy()
|
|
89
96
|
lines = axes.plot(
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
x,
|
|
98
|
+
y,
|
|
92
99
|
color=style.color,
|
|
93
100
|
alpha=style.alpha,
|
|
94
101
|
marker=style.marker,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
from matplotlib.lines import Line2D
|
|
@@ -126,10 +126,18 @@ def _plotPercentiles(
|
|
|
126
126
|
axes: Axes, plot_config: PlotConfig, data: DataFrame, ensemble_label: str
|
|
127
127
|
) -> None:
|
|
128
128
|
style = plot_config.getStatisticsStyle("mean")
|
|
129
|
+
if plot_config.depth_y_axis:
|
|
130
|
+
axes.yaxis.set_inverted(True)
|
|
131
|
+
|
|
132
|
+
def xy_order(x: Any, y: Any) -> tuple[Any, Any]:
|
|
133
|
+
if plot_config.depth_y_axis:
|
|
134
|
+
return (y, x)
|
|
135
|
+
else:
|
|
136
|
+
return (x, y)
|
|
137
|
+
|
|
129
138
|
if style.isVisible():
|
|
130
139
|
axes.plot(
|
|
131
|
-
data.index.values,
|
|
132
|
-
data["Mean"].values,
|
|
140
|
+
*xy_order(data.index.values, data["Mean"].values),
|
|
133
141
|
alpha=style.alpha,
|
|
134
142
|
linestyle=style.line_style,
|
|
135
143
|
color=style.color,
|
|
@@ -141,8 +149,7 @@ def _plotPercentiles(
|
|
|
141
149
|
style = plot_config.getStatisticsStyle("p50")
|
|
142
150
|
if style.isVisible():
|
|
143
151
|
axes.plot(
|
|
144
|
-
data.index.values,
|
|
145
|
-
data["p50"].values,
|
|
152
|
+
*xy_order(data.index.values, data["p50"].values),
|
|
146
153
|
alpha=style.alpha,
|
|
147
154
|
linestyle=style.line_style,
|
|
148
155
|
color=style.color,
|
|
@@ -153,7 +160,13 @@ def _plotPercentiles(
|
|
|
153
160
|
|
|
154
161
|
style = plot_config.getStatisticsStyle("std")
|
|
155
162
|
_plotPercentile(
|
|
156
|
-
axes,
|
|
163
|
+
axes,
|
|
164
|
+
style,
|
|
165
|
+
data.index.values,
|
|
166
|
+
data["std+"].values,
|
|
167
|
+
data["std-"].values,
|
|
168
|
+
0.5,
|
|
169
|
+
plot_config.depth_y_axis,
|
|
157
170
|
)
|
|
158
171
|
|
|
159
172
|
style = plot_config.getStatisticsStyle("min-max")
|
|
@@ -164,16 +177,29 @@ def _plotPercentiles(
|
|
|
164
177
|
data["Maximum"].values,
|
|
165
178
|
data["Minimum"].values,
|
|
166
179
|
0.5,
|
|
180
|
+
plot_config.depth_y_axis,
|
|
167
181
|
)
|
|
168
182
|
|
|
169
183
|
style = plot_config.getStatisticsStyle("p10-p90")
|
|
170
184
|
_plotPercentile(
|
|
171
|
-
axes,
|
|
185
|
+
axes,
|
|
186
|
+
style,
|
|
187
|
+
data.index.values,
|
|
188
|
+
data["p90"].values,
|
|
189
|
+
data["p10"].values,
|
|
190
|
+
0.5,
|
|
191
|
+
plot_config.depth_y_axis,
|
|
172
192
|
)
|
|
173
193
|
|
|
174
194
|
style = plot_config.getStatisticsStyle("p33-p67")
|
|
175
195
|
_plotPercentile(
|
|
176
|
-
axes,
|
|
196
|
+
axes,
|
|
197
|
+
style,
|
|
198
|
+
data.index.values,
|
|
199
|
+
data["p67"].values,
|
|
200
|
+
data["p33"].values,
|
|
201
|
+
0.5,
|
|
202
|
+
plot_config.depth_y_axis,
|
|
177
203
|
)
|
|
178
204
|
|
|
179
205
|
|
|
@@ -184,24 +210,39 @@ def _plotPercentile(
|
|
|
184
210
|
top_line_data: npt.ArrayLike,
|
|
185
211
|
bottom_line_data: npt.ArrayLike,
|
|
186
212
|
alpha_multiplier: float,
|
|
213
|
+
inverted: bool = False,
|
|
187
214
|
) -> None:
|
|
188
215
|
alpha = style.alpha
|
|
189
216
|
line_style = style.line_style
|
|
190
217
|
color = style.color
|
|
191
218
|
marker = style.marker
|
|
192
219
|
|
|
220
|
+
def xy_order(x: Any, y: Any) -> tuple[Any, Any]:
|
|
221
|
+
if inverted:
|
|
222
|
+
return (y, x)
|
|
223
|
+
else:
|
|
224
|
+
return (x, y)
|
|
225
|
+
|
|
193
226
|
if line_style == "#":
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
227
|
+
if inverted:
|
|
228
|
+
axes.fill_betweenx(
|
|
229
|
+
index_values,
|
|
230
|
+
bottom_line_data,
|
|
231
|
+
top_line_data,
|
|
232
|
+
alpha=alpha * alpha_multiplier,
|
|
233
|
+
color=color,
|
|
234
|
+
)
|
|
235
|
+
else:
|
|
236
|
+
axes.fill_between(
|
|
237
|
+
index_values,
|
|
238
|
+
bottom_line_data,
|
|
239
|
+
top_line_data,
|
|
240
|
+
alpha=alpha * alpha_multiplier,
|
|
241
|
+
color=color,
|
|
242
|
+
)
|
|
201
243
|
elif style.isVisible():
|
|
202
244
|
axes.plot(
|
|
203
|
-
index_values,
|
|
204
|
-
bottom_line_data,
|
|
245
|
+
*xy_order(index_values, bottom_line_data),
|
|
205
246
|
alpha=alpha,
|
|
206
247
|
linestyle=line_style,
|
|
207
248
|
color=color,
|
|
@@ -210,8 +251,7 @@ def _plotPercentile(
|
|
|
210
251
|
markersize=style.size,
|
|
211
252
|
)
|
|
212
253
|
axes.plot(
|
|
213
|
-
index_values,
|
|
214
|
-
top_line_data,
|
|
254
|
+
*xy_order(index_values, top_line_data),
|
|
215
255
|
alpha=alpha,
|
|
216
256
|
linestyle=line_style,
|
|
217
257
|
color=color,
|
ert/mode_definitions.py
CHANGED
|
@@ -6,6 +6,7 @@ TEST_RUN_MODE = "test_run"
|
|
|
6
6
|
WORKFLOW_MODE = "workflow"
|
|
7
7
|
EVALUATE_ENSEMBLE_MODE = "evaluate_ensemble"
|
|
8
8
|
MANUAL_UPDATE_MODE = "manual_update"
|
|
9
|
+
MANUAL_ENIF_UPDATE_MODE = "manual_enif_update"
|
|
9
10
|
|
|
10
11
|
MODULE_MODE = {
|
|
11
12
|
"EnsembleInformationFilter": ENIF_MODE,
|
|
@@ -15,4 +16,5 @@ MODULE_MODE = {
|
|
|
15
16
|
"SingleTestRun": TEST_RUN_MODE,
|
|
16
17
|
"EvaluateEnsemble": EVALUATE_ENSEMBLE_MODE,
|
|
17
18
|
"ManualUpdate": MANUAL_UPDATE_MODE,
|
|
19
|
+
"ManualEnIFUpdate": MANUAL_ENIF_UPDATE_MODE,
|
|
18
20
|
}
|