From 5b2b59d2eb92fc6482bbf41071e7840fb008528d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Eide?= Date: Fri, 1 Dec 2023 14:27:42 +0100 Subject: [PATCH] Fixes --- .../ensemble_evaluator/sync_ws_duplexer.py | 1 + src/ert/gui/simulation/manual_update_panel.py | 17 +- src/ert/gui/simulation/simulation_panel.py | 4 +- .../gui/test_full_manual_update_workflow.py | 154 +++++++++++++++++- tests/unit_tests/gui/test_main_window.py | 10 +- 5 files changed, 171 insertions(+), 15 deletions(-) diff --git a/src/ert/ensemble_evaluator/sync_ws_duplexer.py b/src/ert/ensemble_evaluator/sync_ws_duplexer.py index a3e4301b8b9..4c76bc64810 100644 --- a/src/ert/ensemble_evaluator/sync_ws_duplexer.py +++ b/src/ert/ensemble_evaluator/sync_ws_duplexer.py @@ -84,6 +84,7 @@ async def _connect(self) -> None: base_url=self._hc_uri, token=self._token, cert=self._cert, + timeout=5, ) self._ws = await connect diff --git a/src/ert/gui/simulation/manual_update_panel.py b/src/ert/gui/simulation/manual_update_panel.py index 1d1afb2bf20..cb838e3d7f1 100644 --- a/src/ert/gui/simulation/manual_update_panel.py +++ b/src/ert/gui/simulation/manual_update_panel.py @@ -1,16 +1,16 @@ from dataclasses import dataclass -from qtpy.QtWidgets import QFormLayout, QLabel, QLineEdit, QCheckBox +from qtpy.QtWidgets import QCheckBox, QFormLayout, QLabel, QLineEdit from ert.gui.ertnotifier import ErtNotifier from ert.gui.ertwidgets import AnalysisModuleEdit, CaseSelector from ert.gui.ertwidgets.copyablelabel import CopyableLabel from ert.gui.ertwidgets.models.activerealizationsmodel import ActiveRealizationsModel from ert.gui.ertwidgets.stringbox import StringBox -from ert.libres_facade import LibresFacade from ert.run_models import ManualUpdate -from ert.validation import ProperNameFormatArgument, RangeStringArgument +from ert.validation import RangeStringArgument +from ...config import AnalysisConfig from .simulation_config_panel import SimulationConfigPanel @@ -45,7 +45,11 @@ def setValidator(self, validator): class ManualUpdatePanel(SimulationConfigPanel): def __init__( - self, facade: LibresFacade, notifier: ErtNotifier, ensemble_size: int + self, + analysis_config: AnalysisConfig, + run_path: str, + notifier: ErtNotifier, + ensemble_size: int, ) -> None: super().__init__(ManualUpdate) self.notifier = notifier @@ -53,7 +57,7 @@ def __init__( self.setObjectName("manual_update_panel") - runpath_label = CopyableLabel(text=facade.run_path_stripped) + runpath_label = CopyableLabel(text=run_path) layout.addRow("Runpath:", runpath_label) number_of_realizations_label = QLabel(f"{ensemble_size}") @@ -70,7 +74,7 @@ def __init__( layout.addRow("Posterior:", self._case_format_field) self._analysis_module_edit = AnalysisModuleEdit( - facade.get_analysis_module("STD_ENKF"), ensemble_size + analysis_config.es_module, ensemble_size ) self._analysis_module_edit.setObjectName("manual_update_edit") layout.addRow("Analysis module:", self._analysis_module_edit) @@ -83,6 +87,7 @@ def __init__( layout.addRow("Active realizations", self._active_realizations_field) self.check_box = QCheckBox() self.check_box.setChecked(True) + self.check_box.setObjectName("evaluate_posterior") layout.addRow("Evaluate posterior after update", self.check_box) self.setLayout(layout) diff --git a/src/ert/gui/simulation/simulation_panel.py b/src/ert/gui/simulation/simulation_panel.py index c5510c0eb36..7487f6b1e53 100644 --- a/src/ert/gui/simulation/simulation_panel.py +++ b/src/ert/gui/simulation/simulation_panel.py @@ -121,7 +121,9 @@ def __init__(self, ert: EnKFMain, notifier: ErtNotifier, config_file: str): simulation_mode_valid, ) self.addSimulationConfigPanel( - ManualUpdatePanel(self.facade, notifier, ensemble_size), + ManualUpdatePanel( + analysis_config, self.facade.run_path_stripped, notifier, ensemble_size + ), simulation_mode_valid, ) diff --git a/tests/unit_tests/gui/test_full_manual_update_workflow.py b/tests/unit_tests/gui/test_full_manual_update_workflow.py index 727c5778ac1..c33276b2548 100644 --- a/tests/unit_tests/gui/test_full_manual_update_workflow.py +++ b/tests/unit_tests/gui/test_full_manual_update_workflow.py @@ -1,14 +1,23 @@ +import contextlib import shutil import numpy as np from qtpy.QtCore import Qt, QTimer -from qtpy.QtWidgets import QApplication, QComboBox, QMessageBox, QPushButton, QWidget +from qtpy.QtWidgets import ( + QApplication, + QCheckBox, + QComboBox, + QMessageBox, + QPushButton, + QWidget, +) from ert.data import MeasuredData from ert.gui.ertwidgets.caselist import CaseList from ert.gui.simulation.ensemble_experiment_panel import EnsembleExperimentPanel from ert.gui.simulation.run_dialog import RunDialog from ert.gui.simulation.simulation_panel import SimulationPanel +from ert.gui.simulation.view import RealizationWidget from ert.run_models import EnsembleExperiment, ManualUpdate from ert.validation import rangestring_to_mask from tests.unit_tests.gui.simulation.test_run_path_dialog import handle_run_path_dialog @@ -16,7 +25,54 @@ from .conftest import get_child, wait_for_child, with_manage_tool -def test_that_the_manual_analysis_tool_works( +def test_that_the_manual_analysis_model_works( + ensemble_experiment_has_run, opened_main_window, qtbot, run_experiment +): + """This runs a full manual update workflow, first running ensemble experiment + where some of the realizations fail, then doing an update followed by a evaluation. + """ + gui = opened_main_window + with contextlib.suppress(FileNotFoundError): + shutil.rmtree("poly_out") + # Select correct experiment in the simulation panel + simulation_panel = gui.findChild(SimulationPanel) + assert isinstance(simulation_panel, SimulationPanel) + simulation_mode_combo = simulation_panel.findChild(QComboBox) + assert isinstance(simulation_mode_combo, QComboBox) + simulation_mode_combo.setCurrentText(ManualUpdate.name()) + + update_panel = get_child(gui, QWidget, name="manual_update_panel") + assert update_panel + + # Click start simulation and agree to the message + start_simulation = simulation_panel.findChild(QWidget, name="start_simulation") + + def handle_dialog(): + qtbot.mouseClick( + wait_for_child(gui, qtbot, QMessageBox).buttons()[0], Qt.LeftButton + ) + + QTimer.singleShot( + 500, lambda: handle_run_path_dialog(gui, qtbot, delete_run_path=False) + ) + + QTimer.singleShot(500, handle_dialog) + qtbot.mouseClick(start_simulation, Qt.LeftButton) + + # The Run dialog opens, click show details and wait until done appears + # then click it + qtbot.waitUntil(lambda: gui.findChild(RunDialog) is not None) + run_dialog = gui.findChild(RunDialog) + + qtbot.mouseClick(run_dialog.show_details_button, Qt.LeftButton) + + qtbot.waitUntil(run_dialog.done_button.isVisible, timeout=200000) + qtbot.waitUntil(lambda: run_dialog._tab_widget.currentWidget() is not None) + + qtbot.mouseClick(run_dialog.done_button, Qt.LeftButton) + + +def test_manual_update_with_ensemble_experiment( ensemble_experiment_has_run, opened_main_window, qtbot, run_experiment ): """This runs a full manual update workflow, first running ensemble experiment @@ -24,4 +80,96 @@ def test_that_the_manual_analysis_tool_works( ensemble experiment again to calculate the forecast of the update. """ gui = opened_main_window - run_experiment(ManualUpdate) + with contextlib.suppress(FileNotFoundError): + shutil.rmtree("poly_out") + # Select correct experiment in the simulation panel + simulation_panel = gui.findChild(SimulationPanel) + assert isinstance(simulation_panel, SimulationPanel) + simulation_mode_combo = simulation_panel.findChild(QComboBox) + assert isinstance(simulation_mode_combo, QComboBox) + simulation_mode_combo.setCurrentText(ManualUpdate.name()) + + update_panel = get_child(gui, QWidget, name="manual_update_panel") + assert update_panel + qtbot.waitUntil( + lambda: gui.findChild(QCheckBox, name="evaluate_posterior") is not None + ) + check_box = gui.findChild(QCheckBox, name="evaluate_posterior") + check_box.setChecked(False) + # Click start simulation and agree to the message + start_simulation = simulation_panel.findChild(QWidget, name="start_simulation") + + def handle_dialog(): + qtbot.mouseClick( + wait_for_child(gui, qtbot, QMessageBox).buttons()[0], Qt.LeftButton + ) + + QTimer.singleShot( + 500, lambda: handle_run_path_dialog(gui, qtbot, delete_run_path=False) + ) + + QTimer.singleShot(500, handle_dialog) + qtbot.mouseClick(start_simulation, Qt.LeftButton) + + # The Run dialog opens, click show details and wait until done appears + # then click it + qtbot.waitUntil(lambda: gui.findChild(RunDialog) is not None) + run_dialog = gui.findChild(RunDialog) + + qtbot.mouseClick(run_dialog.show_details_button, Qt.LeftButton) + + qtbot.waitUntil(run_dialog.done_button.isVisible, timeout=200000) + qtbot.waitUntil(lambda: run_dialog._tab_widget.currentWidget() is not None) + + qtbot.mouseClick(run_dialog.done_button, Qt.LeftButton) + + with contextlib.suppress(FileNotFoundError): + shutil.rmtree("poly_out") + # Select correct experiment in the simulation panel + simulation_panel = gui.findChild(SimulationPanel) + assert isinstance(simulation_panel, SimulationPanel) + simulation_mode_combo = simulation_panel.findChild(QComboBox) + assert isinstance(simulation_mode_combo, QComboBox) + simulation_mode_combo.setCurrentText(EnsembleExperiment.name()) + + config_panel = get_child(gui, QWidget, name="Ensemble_experiment_panel") + assert config_panel + + print(1) + + # Click start simulation and agree to the message + start_simulation = simulation_panel.findChild(QWidget, name="start_simulation") + + def handle_dialog(): + qtbot.mouseClick( + wait_for_child(gui, qtbot, QMessageBox).buttons()[0], Qt.LeftButton + ) + + QTimer.singleShot( + 500, lambda: handle_run_path_dialog(gui, qtbot, delete_run_path=False) + ) + + QTimer.singleShot(500, handle_dialog) + qtbot.mouseClick(start_simulation, Qt.LeftButton) + + # The Run dialog opens, click show details and wait until done appears + # then click it + qtbot.waitUntil(lambda: gui.findChild(RunDialog) is not None) + run_dialog = gui.findChild(RunDialog) + + qtbot.mouseClick(run_dialog.show_details_button, Qt.LeftButton) + + qtbot.waitUntil(run_dialog.done_button.isVisible, timeout=200000) + qtbot.waitUntil(lambda: run_dialog._tab_widget.currentWidget() is not None) + + # Assert that the number of boxes in the detailed view is + # equal to the number of realizations + realization_widget = run_dialog._tab_widget.currentWidget() + assert isinstance(realization_widget, RealizationWidget) + list_model = realization_widget._real_view.model() + assert ( + list_model.rowCount() + == simulation_panel.ert.ert_config.model_config.num_realizations + ) + + qtbot.mouseClick(run_dialog.done_button, Qt.LeftButton) diff --git a/tests/unit_tests/gui/test_main_window.py b/tests/unit_tests/gui/test_main_window.py index 539f0983dc5..c9fec9bf0e4 100644 --- a/tests/unit_tests/gui/test_main_window.py +++ b/tests/unit_tests/gui/test_main_window.py @@ -156,7 +156,7 @@ def test_that_the_ui_show_no_errors_and_enables_update_for_poly_example(qapp): with add_gui_log_handler() as log_handler: gui, *_ = ert.gui.main._start_initial_gui_window(args, log_handler) combo_box = get_child(gui, QComboBox, name="Simulation_mode") - assert combo_box.count() == 5 + assert combo_box.count() == 6 for i in range(combo_box.count()): assert combo_box.model().item(i).isEnabled() @@ -175,7 +175,7 @@ def test_gui_shows_a_warning_and_disables_update_when_there_are_no_observations( with add_gui_log_handler() as log_handler: gui, *_ = ert.gui.main._start_initial_gui_window(args, log_handler) combo_box = get_child(gui, QComboBox, name="Simulation_mode") - assert combo_box.count() == 5 + assert combo_box.count() == 6 for i in range(2): assert combo_box.model().item(i).isEnabled() @@ -202,7 +202,7 @@ def test_gui_shows_a_warning_and_disables_update_when_parameters_are_missing( with add_gui_log_handler() as log_handler: gui, *_ = ert.gui.main._start_initial_gui_window(args, log_handler) combo_box = get_child(gui, QComboBox, name="Simulation_mode") - assert combo_box.count() == 5 + assert combo_box.count() == 6 for i in range(2): assert combo_box.model().item(i).isEnabled() @@ -367,7 +367,7 @@ def test_that_es_mda_is_disabled_when_weights_are_invalid(qtbot): assert gui.windowTitle() == "ERT - poly.ert" combo_box = get_child(gui, QComboBox, name="Simulation_mode") - assert combo_box.count() == 5 + assert combo_box.count() == 6 combo_box.setCurrentIndex(3) assert ( @@ -817,7 +817,7 @@ def test_that_es_mda_restart_run_box_is_disabled_when_there_are_no_cases(qtbot): assert gui.windowTitle() == "ERT - poly.ert" combo_box = get_child(gui, QComboBox, name="Simulation_mode") - assert combo_box.count() == 5 + assert combo_box.count() == 6 combo_box.setCurrentIndex(3) assert (