Skip to content

Commit

Permalink
Add DesignMatrixPanel to show DataFrame parameters in a table
Browse files Browse the repository at this point in the history
- Set button disabled when design_matrix is not present
- Add test for design matrix show parameters button
  • Loading branch information
xjules committed Oct 11, 2024
1 parent 072decc commit 313e578
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 8 deletions.
48 changes: 42 additions & 6 deletions src/ert/gui/simulation/ensemble_experiment_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,21 @@

from qtpy import QtCore
from qtpy.QtCore import Slot
from qtpy.QtWidgets import QFormLayout, QLabel
from qtpy.QtWidgets import QFormLayout, QHBoxLayout, QLabel, QPushButton

from ert.config import AnalysisConfig, DesignMatrix
from ert.gui.ertnotifier import ErtNotifier
from ert.gui.ertwidgets import (
ActiveRealizationsModel,
CopyableLabel,
StringBox,
TextModel,
)
from ert.gui.tools.design_matrix.design_matrix_panel import DesignMatrixPanel
from ert.mode_definitions import ENSEMBLE_EXPERIMENT_MODE
from ert.run_models import EnsembleExperiment
from ert.validation import RangeStringArgument
from ert.validation.proper_name_argument import (
ExperimentValidation,
ProperNameArgument,
)
from ert.validation.proper_name_argument import ExperimentValidation, ProperNameArgument

from .experiment_config_panel import ExperimentConfigPanel

Expand All @@ -31,7 +30,13 @@ class Arguments:


class EnsembleExperimentPanel(ExperimentConfigPanel):
def __init__(self, ensemble_size: int, run_path: str, notifier: ErtNotifier):
def __init__(
self,
analysis_config: AnalysisConfig,
ensemble_size: int,
run_path: str,
notifier: ErtNotifier,
):
self.notifier = notifier
super().__init__(EnsembleExperiment)
self.setObjectName("Ensemble_experiment_panel")
Expand Down Expand Up @@ -78,6 +83,23 @@ def __init__(self, ensemble_size: int, run_path: str, notifier: ErtNotifier):
)
layout.addRow("Active realizations", self._active_realizations_field)

design_matrix = analysis_config.design_matrix
dm_param_button = QPushButton("Show parameters")
dm_param_button.setObjectName("show-dm-parameters")
dm_param_button.setMinimumWidth(50)

button_layout = QHBoxLayout()
button_layout.addWidget(dm_param_button)
button_layout.addStretch() # Add stretch to push the button to the left

layout.addRow("Design Matrix", button_layout)
if design_matrix is not None:
dm_param_button.clicked.connect(
lambda: self.on_dm_params_clicked(design_matrix)
)
else:
dm_param_button.setDisabled(True)

self.setLayout(layout)

self._active_realizations_field.getValidationSupport().validationChanged.connect(
Expand All @@ -92,6 +114,20 @@ def __init__(self, ensemble_size: int, run_path: str, notifier: ErtNotifier):

self.notifier.ertChanged.connect(self._update_experiment_name_placeholder)

def on_dm_params_clicked(self, design_matrix: DesignMatrix) -> None:
if design_matrix is not None:
if design_matrix.design_matrix_df is None:
design_matrix.read_design_matrix()
if (
design_matrix.design_matrix_df is not None
and not design_matrix.design_matrix_df.empty
):
viewer = DesignMatrixPanel(design_matrix.design_matrix_df)
viewer.setMinimumHeight(500)
viewer.setMinimumWidth(1000)
viewer.adjustSize()
viewer.exec_()

@Slot(ExperimentConfigPanel)
def experimentTypeChanged(self, w: ExperimentConfigPanel) -> None:
if isinstance(w, EnsembleExperimentPanel):
Expand Down
5 changes: 3 additions & 2 deletions src/ert/gui/simulation/experiment_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,9 @@ def __init__(
SingleTestRunPanel(run_path, notifier),
True,
)
analysis_config = config.analysis_config
self.addExperimentConfigPanel(
EnsembleExperimentPanel(ensemble_size, run_path, notifier),
EnsembleExperimentPanel(analysis_config, ensemble_size, run_path, notifier),
True,
)
self.addExperimentConfigPanel(
Expand All @@ -154,7 +155,7 @@ def __init__(
experiment_type_valid = bool(
config.ensemble_config.parameter_configs and config.observations
)
analysis_config = config.analysis_config

self.addExperimentConfigPanel(
MultipleDataAssimilationPanel(
analysis_config, run_path, notifier, ensemble_size
Expand Down
47 changes: 47 additions & 0 deletions src/ert/gui/tools/design_matrix/design_matrix_panel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from typing import Optional

import pandas as pd
from qtpy.QtGui import QStandardItem, QStandardItemModel
from qtpy.QtWidgets import QDialog, QTableView, QVBoxLayout, QWidget


class DesignMatrixPanel(QDialog):
def __init__(
self, design_matrix_df: pd.DataFrame, parent: Optional[QWidget] = None
) -> None:
super().__init__(parent)

self.setWindowTitle("Design matrix parameters viewer")

self.table_view = QTableView(self)
self.table_view.setEditTriggers(QTableView.NoEditTriggers)

self.model = self.create_model(design_matrix_df)
self.table_view.setModel(self.model)

self.table_view.resizeColumnsToContents()
self.table_view.resizeRowsToContents()

layout = QVBoxLayout()
layout.addWidget(self.table_view)
self.setLayout(layout)
self.adjustSize()

@staticmethod
def create_model(design_matrix_df: pd.DataFrame) -> QStandardItemModel:
model = QStandardItemModel()

if isinstance(design_matrix_df.columns, pd.MultiIndex):
header_labels = [str(col[-1]) for col in design_matrix_df.columns]
else:
header_labels = design_matrix_df.columns.astype(str).tolist()

model.setHorizontalHeaderLabels(header_labels)

for index, _ in design_matrix_df.iterrows():
items = [
QStandardItem(str(design_matrix_df.at[index, col]))
for col in design_matrix_df.columns
]
model.appendRow(items)
return model
43 changes: 43 additions & 0 deletions tests/ert/unit_tests/gui/simulation/test_run_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,3 +708,46 @@ def test_that_stdout_and_stderr_buttons_react_to_file_content(

with qtbot.waitSignal(run_dialog.accepted, timeout=30000):
run_dialog.close()


@pytest.mark.integration_test
@pytest.mark.usefixtures("use_tmpdir")
@pytest.mark.parametrize(
"design_matrix_entry",
(True, False),
)
def test_that_design_matrix_show_parameters_button_is_enabled(
design_matrix_entry, qtbot: QtBot, storage
):
with open("design_matrix.xlsx", "w", encoding="utf-8"):
pass
config_file = "minimal_config.ert"
with open(config_file, "w", encoding="utf-8") as f:
f.write("NUM_REALIZATIONS 1")
if design_matrix_entry:
f.write(
"\nDESIGN_MATRIX design_matrix.xlsx DESIGN_SHEET:DesignSheet01 DEFAULT_SHEET:DefaultValues"
)

args_mock = Mock()
args_mock.config = config_file

ert_config = ErtConfig.from_file(config_file)
with StorageService.init_service(
project=os.path.abspath(ert_config.ens_path),
):
gui = _setup_main_window(ert_config, args_mock, GUILogHandler(), storage)
experiment_panel = gui.findChild(ExperimentPanel)
assert isinstance(experiment_panel, ExperimentPanel)

simulation_mode_combo = experiment_panel.findChild(QComboBox)
assert isinstance(simulation_mode_combo, QComboBox)

simulation_mode_combo.setCurrentText(EnsembleExperiment.name())
simulation_settings = gui.findChild(EnsembleExperimentPanel)
show_dm_parameters = simulation_settings.findChild(
QPushButton, "show-dm-parameters"
)

assert isinstance(show_dm_parameters, QPushButton)
assert show_dm_parameters.isEnabled() == design_matrix_entry

0 comments on commit 313e578

Please sign in to comment.