ert 17.0.0__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/__main__.py +28 -13
- ert/analysis/_enif_update.py +8 -4
- ert/analysis/_es_update.py +19 -6
- ert/analysis/_update_commons.py +16 -6
- ert/cli/main.py +13 -6
- ert/cli/monitor.py +7 -0
- ert/config/__init__.py +15 -6
- ert/config/_create_observation_dataframes.py +117 -20
- ert/config/_get_num_cpu.py +1 -1
- ert/config/_observations.py +91 -2
- ert/config/_read_summary.py +8 -6
- ert/config/design_matrix.py +51 -24
- ert/config/distribution.py +1 -1
- ert/config/ensemble_config.py +9 -17
- ert/config/ert_config.py +103 -19
- ert/config/everest_control.py +234 -0
- ert/config/{everest_objective_config.py → everest_response.py} +24 -15
- ert/config/field.py +96 -84
- ert/config/forward_model_step.py +122 -17
- ert/config/gen_data_config.py +5 -10
- ert/config/gen_kw_config.py +5 -35
- 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_keywords.py +2 -0
- ert/config/parsing/config_schema.py +23 -3
- ert/config/parsing/config_schema_deprecations.py +3 -14
- 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 +4 -5
- 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 +59 -16
- 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/common.py +1 -1
- ert/dark_storage/compute/misfits.py +11 -7
- ert/dark_storage/endpoints/compute/misfits.py +6 -4
- ert/dark_storage/endpoints/experiment_server.py +12 -9
- ert/dark_storage/endpoints/experiments.py +2 -2
- ert/dark_storage/endpoints/observations.py +8 -6
- ert/dark_storage/endpoints/parameters.py +2 -18
- ert/dark_storage/endpoints/responses.py +24 -5
- 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 +212 -3
- 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/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/pathchooser.py +0 -3
- ert/gui/ertwidgets/searchbox.py +13 -4
- ert/gui/{suggestor → ertwidgets/suggestor}/_suggestor_message.py +13 -4
- ert/gui/{suggestor → ertwidgets/suggestor}/suggestor.py +63 -30
- ert/gui/main.py +37 -8
- ert/gui/main_window.py +1 -7
- 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 +16 -3
- 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 +27 -20
- ert/gui/simulation/single_test_run_panel.py +2 -2
- ert/gui/summarypanel.py +20 -1
- ert/gui/tools/load_results/load_results_panel.py +1 -1
- ert/gui/tools/manage_experiments/export_dialog.py +136 -0
- ert/gui/tools/manage_experiments/storage_info_widget.py +121 -16
- ert/gui/tools/manage_experiments/storage_widget.py +1 -2
- ert/gui/tools/plot/plot_api.py +37 -25
- ert/gui/tools/plot/plot_widget.py +10 -2
- ert/gui/tools/plot/plot_window.py +38 -18
- 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 +12 -3
- 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/mode_definitions.py +2 -0
- ert/plugins/__init__.py +0 -1
- 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 -2
- ert/plugins/hook_specifications/jobs.py +0 -9
- ert/plugins/plugin_manager.py +6 -33
- ert/resources/forward_models/run_reservoirsimulator.py +8 -3
- ert/resources/shell_scripts/delete_directory.py +2 -2
- ert/run_models/__init__.py +18 -5
- ert/run_models/_create_run_path.py +131 -37
- 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 +159 -46
- 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 +81 -21
- ert/run_models/multiple_data_assimilation.py +22 -11
- ert/run_models/run_model.py +64 -55
- 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 +37 -20
- 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 +2 -0
- ert/storage/local_ensemble.py +38 -12
- ert/storage/local_experiment.py +8 -16
- ert/storage/local_storage.py +68 -42
- ert/storage/migration/to11.py +1 -1
- 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/to8.py +4 -4
- ert/substitutions.py +12 -28
- ert/validation/active_range.py +7 -7
- ert/validation/rangestring.py +16 -16
- ert/workflow_runner.py +2 -1
- {ert-17.0.0.dist-info → ert-19.0.0rc2.dist-info}/METADATA +9 -8
- {ert-17.0.0.dist-info → ert-19.0.0rc2.dist-info}/RECORD +208 -205
- {ert-17.0.0.dist-info → ert-19.0.0rc2.dist-info}/WHEEL +1 -1
- everest/api/everest_data_api.py +14 -1
- everest/bin/config_branch_script.py +3 -6
- everest/bin/everconfigdump_script.py +1 -9
- everest/bin/everest_script.py +21 -11
- everest/bin/everlint_script.py +0 -2
- everest/bin/kill_script.py +2 -2
- everest/bin/monitor_script.py +2 -2
- everest/bin/utils.py +8 -4
- everest/bin/visualization_script.py +6 -14
- 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 +75 -42
- 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 +17 -11
- everest/config_file_loader.py +13 -4
- everest/detached/client.py +3 -3
- everest/detached/everserver.py +7 -8
- everest/everest_storage.py +6 -12
- everest/gui/everest_client.py +2 -3
- 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/config/ext_param_config.py +0 -106
- 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 -69
- ert/gui/tools/export/exporter.py +0 -36
- 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-17.0.0.dist-info → ert-19.0.0rc2.dist-info}/entry_points.txt +0 -0
- {ert-17.0.0.dist-info → ert-19.0.0rc2.dist-info}/licenses/COPYING +0 -0
- {ert-17.0.0.dist-info → ert-19.0.0rc2.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from .activerealizationsmodel import ActiveRealizationsModel
|
|
2
|
+
from .ertsummary import ErtSummary
|
|
2
3
|
from .path_model import PathModel
|
|
3
4
|
from .selectable_list_model import SelectableListModel
|
|
4
5
|
from .targetensemblemodel import TargetEnsembleModel
|
|
@@ -7,6 +8,7 @@ from .valuemodel import ValueModel
|
|
|
7
8
|
|
|
8
9
|
__all__ = [
|
|
9
10
|
"ActiveRealizationsModel",
|
|
11
|
+
"ErtSummary",
|
|
10
12
|
"PathModel",
|
|
11
13
|
"SelectableListModel",
|
|
12
14
|
"TargetEnsembleModel",
|
|
@@ -2,9 +2,10 @@ from collections.abc import Collection
|
|
|
2
2
|
|
|
3
3
|
from typing_extensions import override
|
|
4
4
|
|
|
5
|
-
from ert.gui.ertwidgets.models.valuemodel import ValueModel
|
|
6
5
|
from ert.validation import ActiveRange, mask_to_rangestring
|
|
7
6
|
|
|
7
|
+
from .valuemodel import ValueModel
|
|
8
|
+
|
|
8
9
|
|
|
9
10
|
class ActiveRealizationsModel(ValueModel):
|
|
10
11
|
def __init__(self, ensemble_size: int, show_default: bool = True) -> None:
|
|
@@ -4,7 +4,8 @@ from typing_extensions import override
|
|
|
4
4
|
|
|
5
5
|
from ert.config import AnalysisConfig
|
|
6
6
|
from ert.gui.ertnotifier import ErtNotifier
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
from .valuemodel import ValueModel
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class TargetEnsembleModel(ValueModel):
|
|
@@ -83,7 +83,6 @@ class PathChooser(QWidget):
|
|
|
83
83
|
if self._model.pathMustExist():
|
|
84
84
|
valid = False
|
|
85
85
|
message = PathChooser.PATH_DOES_NOT_EXIST_MSG
|
|
86
|
-
# todo: check if new (non-existing) file has directory or file format?
|
|
87
86
|
elif path_exists:
|
|
88
87
|
if self._model.pathMustBeExecutable() and is_file and not is_executable:
|
|
89
88
|
valid = False
|
|
@@ -122,8 +121,6 @@ class PathChooser(QWidget):
|
|
|
122
121
|
|
|
123
122
|
def selectPath(self) -> None:
|
|
124
123
|
"""Pops up the 'select a file/directory' dialog"""
|
|
125
|
-
# todo: This probably needs some reworking to work properly with
|
|
126
|
-
# different scenarios... (file + dir)
|
|
127
124
|
self._editing = True
|
|
128
125
|
current_directory = self.getPath()
|
|
129
126
|
|
ert/gui/ertwidgets/searchbox.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Any
|
|
2
2
|
|
|
3
|
-
from PyQt6.QtCore import Qt
|
|
3
|
+
from PyQt6.QtCore import Qt, QTimer
|
|
4
4
|
from PyQt6.QtCore import pyqtSignal as Signal
|
|
5
5
|
from PyQt6.QtGui import QColor, QFocusEvent, QKeyEvent
|
|
6
6
|
from PyQt6.QtWidgets import QLineEdit
|
|
@@ -12,16 +12,25 @@ class SearchBox(QLineEdit):
|
|
|
12
12
|
|
|
13
13
|
filterChanged = Signal(object)
|
|
14
14
|
|
|
15
|
-
def __init__(self) -> None:
|
|
15
|
+
def __init__(self, debounce_timeout: int = 1000) -> None:
|
|
16
16
|
QLineEdit.__init__(self)
|
|
17
17
|
|
|
18
18
|
self.setToolTip("Type to search!")
|
|
19
19
|
self.active_color = self.palette().color(self.foregroundRole())
|
|
20
20
|
self.disable_search = True
|
|
21
21
|
self.presentSearch()
|
|
22
|
-
self.textChanged.connect(self.
|
|
22
|
+
self.textChanged.connect(self._start_debounce_timer)
|
|
23
|
+
self._debounce_timout = debounce_timeout
|
|
24
|
+
self._debounce_timer = QTimer(self)
|
|
25
|
+
self._debounce_timer.setSingleShot(True)
|
|
26
|
+
self._debounce_timer.timeout.connect(self._emit_filter_changed)
|
|
23
27
|
|
|
24
|
-
def
|
|
28
|
+
def _start_debounce_timer(self, _filter: Any) -> None:
|
|
29
|
+
if not self._debounce_timer.isActive():
|
|
30
|
+
self._debounce_timer.start(self._debounce_timout)
|
|
31
|
+
self._debounce_timer.setInterval(self._debounce_timout)
|
|
32
|
+
|
|
33
|
+
def _emit_filter_changed(self) -> None:
|
|
25
34
|
self.filterChanged.emit(self.filter())
|
|
26
35
|
|
|
27
36
|
def filter(self) -> str:
|
|
@@ -13,10 +13,11 @@ from PyQt6.QtWidgets import (
|
|
|
13
13
|
QVBoxLayout,
|
|
14
14
|
QWidget,
|
|
15
15
|
)
|
|
16
|
+
from typing_extensions import override
|
|
16
17
|
|
|
17
18
|
from ert.gui import is_dark_mode
|
|
18
19
|
|
|
19
|
-
from ..
|
|
20
|
+
from ..copy_button import CopyButton
|
|
20
21
|
from ._colors import (
|
|
21
22
|
BLUE_BACKGROUND,
|
|
22
23
|
BLUE_TEXT,
|
|
@@ -33,6 +34,16 @@ def _svg_icon(image_name: str) -> QSvgWidget:
|
|
|
33
34
|
return widget
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
class _CopyButton(CopyButton):
|
|
38
|
+
def __init__(self, message: str) -> None:
|
|
39
|
+
super().__init__()
|
|
40
|
+
self.message = message
|
|
41
|
+
|
|
42
|
+
@override
|
|
43
|
+
def copy(self) -> None:
|
|
44
|
+
self.copy_text(self.message)
|
|
45
|
+
|
|
46
|
+
|
|
36
47
|
class SuggestorMessage(QWidget):
|
|
37
48
|
def __init__(
|
|
38
49
|
self,
|
|
@@ -100,9 +111,7 @@ class SuggestorMessage(QWidget):
|
|
|
100
111
|
else:
|
|
101
112
|
self._expand_collapse_label = QLabel()
|
|
102
113
|
self._hbox.addWidget(self.lbl, alignment=Qt.AlignmentFlag.AlignTop)
|
|
103
|
-
self._hbox.addWidget(
|
|
104
|
-
_CopyButton(QLabel(message)), alignment=Qt.AlignmentFlag.AlignTop
|
|
105
|
-
)
|
|
114
|
+
self._hbox.addWidget(_CopyButton(message), alignment=Qt.AlignmentFlag.AlignTop)
|
|
106
115
|
|
|
107
116
|
def _toggle_expand(self, _link: Any) -> None:
|
|
108
117
|
if self._expanded:
|
|
@@ -19,9 +19,11 @@ from PyQt6.QtWidgets import (
|
|
|
19
19
|
QVBoxLayout,
|
|
20
20
|
QWidget,
|
|
21
21
|
)
|
|
22
|
+
from typing_extensions import override
|
|
22
23
|
|
|
23
24
|
from ert.gui import is_dark_mode
|
|
24
25
|
|
|
26
|
+
from .. import CopyButton
|
|
25
27
|
from ._colors import BLUE_TEXT
|
|
26
28
|
from ._suggestor_message import SuggestorMessage
|
|
27
29
|
|
|
@@ -105,6 +107,32 @@ QPushButton:hover {{
|
|
|
105
107
|
"""
|
|
106
108
|
|
|
107
109
|
|
|
110
|
+
class _CopyAllButton(CopyButton):
|
|
111
|
+
def __init__(
|
|
112
|
+
self,
|
|
113
|
+
errors: list[ErrorInfo],
|
|
114
|
+
warnings: list[WarningInfo],
|
|
115
|
+
deprecations: list[WarningInfo],
|
|
116
|
+
) -> None:
|
|
117
|
+
super().__init__()
|
|
118
|
+
self.setText(" Copy all messages")
|
|
119
|
+
self.all_messages = "\n\n".join(
|
|
120
|
+
[
|
|
121
|
+
f"{info.message}" + (f"\n{info.location()}" if info.location() else "")
|
|
122
|
+
for info in (errors + warnings + deprecations)
|
|
123
|
+
]
|
|
124
|
+
)
|
|
125
|
+
self.setStyleSheet(SECONDARY_BUTTON_STYLE)
|
|
126
|
+
|
|
127
|
+
@override
|
|
128
|
+
def copy(self) -> None:
|
|
129
|
+
logger.info(
|
|
130
|
+
"Copy all button in Suggestor used. "
|
|
131
|
+
f"Copied {len(self.all_messages)} characters"
|
|
132
|
+
)
|
|
133
|
+
self.copy_text(self.all_messages)
|
|
134
|
+
|
|
135
|
+
|
|
108
136
|
class Suggestor(QWidget):
|
|
109
137
|
def __init__(
|
|
110
138
|
self,
|
|
@@ -145,7 +173,24 @@ class Suggestor(QWidget):
|
|
|
145
173
|
data_layout.addWidget(self._help_panel(help_links))
|
|
146
174
|
self.__layout.addWidget(data_widget)
|
|
147
175
|
|
|
148
|
-
|
|
176
|
+
action_buttons = QWidget(parent=self)
|
|
177
|
+
action_buttons_layout = QHBoxLayout()
|
|
178
|
+
action_buttons_layout.setContentsMargins(0, 24, 0, 0)
|
|
179
|
+
|
|
180
|
+
if any([errors, warnings, deprecations]):
|
|
181
|
+
action_buttons_layout.addWidget(
|
|
182
|
+
_CopyAllButton(errors, warnings, deprecations)
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
action_buttons_layout.addStretch()
|
|
186
|
+
|
|
187
|
+
if continue_action:
|
|
188
|
+
action_buttons_layout.addWidget(self._continue_button())
|
|
189
|
+
|
|
190
|
+
action_buttons_layout.addWidget(self._close_button())
|
|
191
|
+
|
|
192
|
+
action_buttons.setLayout(action_buttons_layout)
|
|
193
|
+
self.__layout.addWidget(action_buttons)
|
|
149
194
|
|
|
150
195
|
def _help_panel(self, help_links: dict[str, str]) -> QFrame:
|
|
151
196
|
help_button_frame = QFrame(parent=self)
|
|
@@ -204,35 +249,23 @@ class Suggestor(QWidget):
|
|
|
204
249
|
area_layout.addWidget(self._messages(errors, warnings, deprecations))
|
|
205
250
|
return problem_area
|
|
206
251
|
|
|
207
|
-
def
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
run = QPushButton("Open ERT")
|
|
225
|
-
run.setStyleSheet(BUTTON_STYLE)
|
|
226
|
-
run.setObjectName("run_ert_button")
|
|
227
|
-
run.pressed.connect(run_pressed)
|
|
228
|
-
buttons_layout.addWidget(run)
|
|
229
|
-
|
|
230
|
-
give_up.setStyleSheet(SECONDARY_BUTTON_STYLE)
|
|
231
|
-
|
|
232
|
-
buttons_layout.addWidget(give_up)
|
|
233
|
-
buttons.setLayout(buttons_layout)
|
|
234
|
-
|
|
235
|
-
return buttons
|
|
252
|
+
def _continue_button(self) -> QWidget:
|
|
253
|
+
assert self._continue_action
|
|
254
|
+
continue_button = QPushButton("Open ERT")
|
|
255
|
+
continue_button.setStyleSheet(BUTTON_STYLE)
|
|
256
|
+
continue_button.setObjectName("run_ert_button")
|
|
257
|
+
continue_button.pressed.connect(self._continue_action)
|
|
258
|
+
continue_button.pressed.connect(self.close)
|
|
259
|
+
return continue_button
|
|
260
|
+
|
|
261
|
+
def _close_button(self) -> QPushButton:
|
|
262
|
+
close_button = QPushButton("Close")
|
|
263
|
+
close_button.setObjectName("close_button")
|
|
264
|
+
close_button.pressed.connect(self.close)
|
|
265
|
+
close_button.setStyleSheet(
|
|
266
|
+
SECONDARY_BUTTON_STYLE if self._continue_action else BUTTON_STYLE
|
|
267
|
+
)
|
|
268
|
+
return close_button
|
|
236
269
|
|
|
237
270
|
def _messages(
|
|
238
271
|
self,
|
ert/gui/main.py
CHANGED
|
@@ -8,12 +8,13 @@ import traceback
|
|
|
8
8
|
import types
|
|
9
9
|
from collections import Counter
|
|
10
10
|
from importlib.resources import files
|
|
11
|
+
from pathlib import Path
|
|
11
12
|
from signal import SIG_DFL, SIGINT, signal
|
|
12
13
|
|
|
13
14
|
from opentelemetry.trace import Status, StatusCode
|
|
14
15
|
from PyQt6.QtCore import QDir
|
|
15
16
|
from PyQt6.QtGui import QIcon
|
|
16
|
-
from PyQt6.QtWidgets import QApplication, QWidget
|
|
17
|
+
from PyQt6.QtWidgets import QApplication, QMessageBox, QWidget
|
|
17
18
|
|
|
18
19
|
from ert.config import (
|
|
19
20
|
ErrorInfo,
|
|
@@ -27,11 +28,16 @@ from ert.gui.tools.event_viewer import (
|
|
|
27
28
|
)
|
|
28
29
|
from ert.namespace import Namespace
|
|
29
30
|
from ert.plugins import ErtRuntimePlugins, get_site_plugins
|
|
30
|
-
from ert.services import
|
|
31
|
-
from ert.storage import
|
|
31
|
+
from ert.services import ErtServer
|
|
32
|
+
from ert.storage import (
|
|
33
|
+
ErtStorageException,
|
|
34
|
+
LocalStorage,
|
|
35
|
+
local_storage_set_ert_config,
|
|
36
|
+
)
|
|
37
|
+
from ert.storage.local_storage import _LOCAL_STORAGE_VERSION, _storage_version
|
|
32
38
|
from ert.trace import trace, tracer
|
|
33
39
|
|
|
34
|
-
from .
|
|
40
|
+
from .ertwidgets import Suggestor
|
|
35
41
|
|
|
36
42
|
logger = logging.getLogger(__name__)
|
|
37
43
|
|
|
@@ -113,7 +119,7 @@ def run_gui(args: Namespace, plugins: ErtRuntimePlugins | None = None) -> int:
|
|
|
113
119
|
return show_window()
|
|
114
120
|
|
|
115
121
|
try:
|
|
116
|
-
with
|
|
122
|
+
with ErtServer.init_service(project=Path(ens_path).absolute()):
|
|
117
123
|
return show_window()
|
|
118
124
|
except PermissionError as pe:
|
|
119
125
|
print(f"Error: {pe}", file=sys.stderr)
|
|
@@ -157,9 +163,32 @@ def _start_initial_gui_window(
|
|
|
157
163
|
storage_path = None
|
|
158
164
|
if ert_config is not None:
|
|
159
165
|
try:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
166
|
+
if LocalStorage.check_migration_needed(Path(ert_config.ens_path)):
|
|
167
|
+
storage_version = _storage_version(Path(ert_config.ens_path))
|
|
168
|
+
current_version = _LOCAL_STORAGE_VERSION
|
|
169
|
+
|
|
170
|
+
migrate_dialog = QMessageBox.warning(
|
|
171
|
+
None,
|
|
172
|
+
f"Migrate storage to version {current_version}?",
|
|
173
|
+
f"Ert storage is version {storage_version} and needs to be migrated"
|
|
174
|
+
f" to version {current_version} to be compatible with the current"
|
|
175
|
+
f" version of Ert\n\n"
|
|
176
|
+
f"After migration, this storage can only be opened with current or"
|
|
177
|
+
f" later versions of Ert\n\n"
|
|
178
|
+
"Do you wish to continue migrating storage?\n",
|
|
179
|
+
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
if migrate_dialog == QMessageBox.StandardButton.Yes:
|
|
183
|
+
logger.info(
|
|
184
|
+
f"Migrating from version {storage_version} to"
|
|
185
|
+
f" version {current_version}"
|
|
186
|
+
)
|
|
187
|
+
else:
|
|
188
|
+
logger.info("Storage migration cancelled by user")
|
|
189
|
+
os._exit(0)
|
|
190
|
+
|
|
191
|
+
LocalStorage.perform_migration(Path(ert_config.ens_path))
|
|
163
192
|
storage_path = ert_config.ens_path
|
|
164
193
|
except ErtStorageException as err:
|
|
165
194
|
validation_messages.errors.append(
|
ert/gui/main_window.py
CHANGED
|
@@ -9,7 +9,7 @@ from pathlib import Path
|
|
|
9
9
|
from PyQt6.QtCore import QCoreApplication, QEvent, QSize, Qt
|
|
10
10
|
from PyQt6.QtCore import pyqtSignal as Signal
|
|
11
11
|
from PyQt6.QtCore import pyqtSlot as Slot
|
|
12
|
-
from PyQt6.QtGui import QAction, QCloseEvent, QCursor,
|
|
12
|
+
from PyQt6.QtGui import QAction, QCloseEvent, QCursor, QIcon, QMouseEvent
|
|
13
13
|
from PyQt6.QtWidgets import (
|
|
14
14
|
QButtonGroup,
|
|
15
15
|
QFrame,
|
|
@@ -31,7 +31,6 @@ from ert.gui.find_ert_info import find_ert_info
|
|
|
31
31
|
from ert.gui.simulation import ExperimentPanel
|
|
32
32
|
from ert.gui.simulation.run_dialog import RunDialog
|
|
33
33
|
from ert.gui.tools.event_viewer import EventViewerTool, GUILogHandler
|
|
34
|
-
from ert.gui.tools.export import ExportTool
|
|
35
34
|
from ert.gui.tools.load_results import LoadResultsTool
|
|
36
35
|
from ert.gui.tools.manage_experiments import ManageExperimentsPanel
|
|
37
36
|
from ert.gui.tools.plot.plot_window import PlotWindow
|
|
@@ -96,7 +95,6 @@ class ErtMainWindow(QMainWindow):
|
|
|
96
95
|
log_handler: GUILogHandler | None = None,
|
|
97
96
|
) -> None:
|
|
98
97
|
QMainWindow.__init__(self)
|
|
99
|
-
self.available_fonts = QFontDatabase.families()
|
|
100
98
|
self.notifier = ErtNotifier()
|
|
101
99
|
self.plugins_tool: PluginsTool | None = None
|
|
102
100
|
self.ert_config = ert_config
|
|
@@ -374,10 +372,6 @@ class ErtMainWindow(QMainWindow):
|
|
|
374
372
|
tools_menu.addAction(self._event_viewer_tool.getAction())
|
|
375
373
|
self.close_signal.connect(self._event_viewer_tool.close_wnd)
|
|
376
374
|
|
|
377
|
-
self.export_tool = ExportTool(self.ert_config, self.notifier)
|
|
378
|
-
self.export_tool.setParent(self)
|
|
379
|
-
tools_menu.addAction(self.export_tool.getAction())
|
|
380
|
-
|
|
381
375
|
self.workflows_tool = WorkflowsTool(self.ert_config, self.notifier)
|
|
382
376
|
self.workflows_tool.setParent(self)
|
|
383
377
|
tools_menu.addAction(self.workflows_tool.getAction())
|
|
@@ -17,6 +17,7 @@ from ert.gui.ertwidgets import (
|
|
|
17
17
|
CopyableLabel,
|
|
18
18
|
StringBox,
|
|
19
19
|
TextModel,
|
|
20
|
+
get_parameters_button,
|
|
20
21
|
)
|
|
21
22
|
from ert.mode_definitions import ENSEMBLE_EXPERIMENT_MODE
|
|
22
23
|
from ert.run_models import EnsembleExperiment
|
|
@@ -24,7 +25,6 @@ from ert.validation import ExperimentValidation, ProperNameArgument
|
|
|
24
25
|
from ert.validation.active_range import ActiveRange
|
|
25
26
|
from ert.validation.range_string_argument import RangeSubsetStringArgument
|
|
26
27
|
|
|
27
|
-
from ..ertwidgets.parameterviewer import get_parameters_button
|
|
28
28
|
from ._design_matrix_panel import DesignMatrixPanel
|
|
29
29
|
from .experiment_config_panel import ExperimentConfigPanel
|
|
30
30
|
|
|
@@ -14,6 +14,7 @@ from ert.gui.ertwidgets import (
|
|
|
14
14
|
StringBox,
|
|
15
15
|
TargetEnsembleModel,
|
|
16
16
|
TextModel,
|
|
17
|
+
get_parameters_button,
|
|
17
18
|
)
|
|
18
19
|
from ert.mode_definitions import ENIF_MODE
|
|
19
20
|
from ert.run_models import EnsembleInformationFilter
|
|
@@ -24,7 +25,6 @@ from ert.validation import (
|
|
|
24
25
|
from ert.validation.active_range import ActiveRange
|
|
25
26
|
from ert.validation.range_string_argument import RangeSubsetStringArgument
|
|
26
27
|
|
|
27
|
-
from ..ertwidgets.parameterviewer import get_parameters_button
|
|
28
28
|
from ._design_matrix_panel import DesignMatrixPanel
|
|
29
29
|
from .experiment_config_panel import ExperimentConfigPanel
|
|
30
30
|
|
|
@@ -16,6 +16,7 @@ from ert.gui.ertwidgets import (
|
|
|
16
16
|
StringBox,
|
|
17
17
|
TargetEnsembleModel,
|
|
18
18
|
TextModel,
|
|
19
|
+
get_parameters_button,
|
|
19
20
|
)
|
|
20
21
|
from ert.mode_definitions import ENSEMBLE_SMOOTHER_MODE
|
|
21
22
|
from ert.run_models import EnsembleSmoother
|
|
@@ -26,7 +27,6 @@ from ert.validation import (
|
|
|
26
27
|
from ert.validation.active_range import ActiveRange
|
|
27
28
|
from ert.validation.range_string_argument import RangeSubsetStringArgument
|
|
28
29
|
|
|
29
|
-
from ..ertwidgets.parameterviewer import get_parameters_button
|
|
30
30
|
from ._design_matrix_panel import DesignMatrixPanel
|
|
31
31
|
from .experiment_config_panel import ExperimentConfigPanel
|
|
32
32
|
|
|
@@ -14,9 +14,9 @@ from ert.gui.ertwidgets import (
|
|
|
14
14
|
CopyableLabel,
|
|
15
15
|
EnsembleSelector,
|
|
16
16
|
StringBox,
|
|
17
|
+
Suggestor,
|
|
17
18
|
)
|
|
18
19
|
from ert.gui.simulation.experiment_config_panel import ExperimentConfigPanel
|
|
19
|
-
from ert.gui.suggestor import Suggestor
|
|
20
20
|
from ert.mode_definitions import EVALUATE_ENSEMBLE_MODE
|
|
21
21
|
from ert.run_models.evaluate_ensemble import EvaluateEnsemble
|
|
22
22
|
from ert.storage import RealizationStorageState
|
|
@@ -55,9 +55,15 @@ def create_md_table(kv: dict[str, str], output: str) -> str:
|
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
def get_simulation_thread(
|
|
58
|
-
model: Any,
|
|
58
|
+
model: Any,
|
|
59
|
+
rerun_failed_realizations: bool = False,
|
|
60
|
+
use_ipc_protocol: bool = False,
|
|
61
|
+
prioritize_private_ip_address: bool = False,
|
|
59
62
|
) -> ErtThread:
|
|
60
|
-
evaluator_server_config = EvaluatorServerConfig(
|
|
63
|
+
evaluator_server_config = EvaluatorServerConfig(
|
|
64
|
+
use_ipc_protocol=use_ipc_protocol,
|
|
65
|
+
prioritize_private_ip_address=prioritize_private_ip_address,
|
|
66
|
+
)
|
|
61
67
|
|
|
62
68
|
def run() -> None:
|
|
63
69
|
model.api.start_simulations_thread(
|
|
@@ -354,6 +360,10 @@ class ExperimentPanel(QWidget):
|
|
|
354
360
|
return
|
|
355
361
|
QApplication.restoreOverrideCursor()
|
|
356
362
|
|
|
363
|
+
self.configuration_summary.log_summary(
|
|
364
|
+
args.mode, model.get_number_of_active_realizations()
|
|
365
|
+
)
|
|
366
|
+
|
|
357
367
|
self._dialog = RunDialog(
|
|
358
368
|
f"Experiment - {self._config_file} {find_ert_info()}",
|
|
359
369
|
model.api,
|
|
@@ -364,7 +374,9 @@ class ExperimentPanel(QWidget):
|
|
|
364
374
|
run_path=Path(self.config.runpath_config.runpath_format_string),
|
|
365
375
|
storage_path=self._notifier.storage.path,
|
|
366
376
|
)
|
|
367
|
-
self._dialog.
|
|
377
|
+
self._dialog.queue_system.setText(
|
|
378
|
+
f"Queue system:\n{model.queue_config.queue_system.formatted_name}"
|
|
379
|
+
)
|
|
368
380
|
self.experiment_started.emit(self._dialog)
|
|
369
381
|
self._simulation_done = False
|
|
370
382
|
self.run_button.setEnabled(self._simulation_done)
|
|
@@ -375,6 +387,7 @@ class ExperimentPanel(QWidget):
|
|
|
375
387
|
rerun_failed_realizations,
|
|
376
388
|
use_ipc_protocol=self.config.queue_config.queue_system
|
|
377
389
|
== QueueSystem.LOCAL,
|
|
390
|
+
prioritize_private_ip_address=self.config.prioritize_private_ip_address,
|
|
378
391
|
)
|
|
379
392
|
self._dialog.setup_event_monitoring(rerun_failed_realizations)
|
|
380
393
|
simulation_thread.start()
|
|
@@ -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)
|