Skip to content

Commit 878bbc4

Browse files
committed
Use Matplotlib's plot customization dialog
1 parent 0676776 commit 878bbc4

3 files changed

Lines changed: 37 additions & 84 deletions

File tree

src/ert/gui/plotting/plot_window.py

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@
5151
from ert.services import ServerBootFail
5252
from ert.utils import log_duration
5353

54-
from .customization_dialog import PlotCustomizer
5554
from .plot_api import EnsembleObject, PlotApi, PlotApiKeyDefinition
56-
from .utils import PlotConfig, PlotContext
55+
from .utils import PlotConfigFactory, PlotContext
5756
from .utils.observation_locations import transform_observation_locations
57+
from .utils.plot_color_palettes import TABLEAU_10_COLOR_CYCLE
5858
from .utils.plot_types import ObservationPlotLocations
5959
from .utils.qt_creator import create_group_box, create_group_layout, create_side_panel
6060
from .widgets.data_type_keys_widget import DataTypeKeysWidget
@@ -206,8 +206,9 @@ def __init__(
206206
self._key_definitions = []
207207
QApplication.restoreOverrideCursor()
208208

209-
self._plot_customizer = PlotCustomizer(self, self._key_definitions)
210-
self._plot_customizer.settingsChanged.connect(self.keySelected)
209+
self._titles: dict[str, str] = {}
210+
self._x_labels: dict[str, str | None] = {}
211+
self._y_labels: dict[str, str | None] = {}
211212
self._central_tab = QTabWidget()
212213

213214
central_widget = QWidget()
@@ -266,7 +267,7 @@ def __init__(
266267

267268
self._ensemble_selection_widget = EnsembleSelectionWidget(
268269
plot_case_objects,
269-
self._plot_customizer.get_plot_config().get_number_of_colors(),
270+
len(TABLEAU_10_COLOR_CYCLE),
270271
)
271272

272273
self._ensemble_selection_widget.ensembleSelectionChanged.connect(
@@ -543,9 +544,10 @@ def fetch_data(
543544
except BaseException as e:
544545
handle_exception(e)
545546

546-
plot_config = PlotConfig.create_copy(
547-
self._plot_customizer.get_plot_config()
548-
)
547+
plot_config = PlotConfigFactory.create_plot_config_for_key(key_def)
548+
plot_config.set_title(self._titles.get(key, key))
549+
plot_config.set_x_label(self._x_labels.get(key))
550+
plot_config.set_y_label(self._y_labels.get(key))
549551
plot_config.set_legend_enabled(self._general_options.legend_checkbox_state)
550552
plot_config.set_grid_enabled(self._general_options.grid_checkbox_state)
551553
plot_config.set_line_color_cycle(self._general_options.get_color_cycle())
@@ -656,7 +658,6 @@ def add_plot_widget(
656658
enabled: bool = True,
657659
) -> None:
658660
plot_widget = PlotWidget(name, plotter)
659-
plot_widget.customizationTriggered.connect(self.toggle_customize_dialog)
660661
plot_widget.axisLabelEditRequested.connect(self._edit_axis_label)
661662
plot_widget.titleEditRequested.connect(self._edit_title)
662663
plot_widget.layer_index_changed.connect(self.layer_index_changed)
@@ -669,11 +670,14 @@ def _edit_axis_label(self, axis: str) -> None:
669670
label_names = {"x": "x-label", "y": "y-label"}
670671
if axis not in label_names:
671672
raise ValueError(f"Unknown axis '{axis}'. Expected 'x' or 'y'.")
673+
key_def = self.getSelectedKey()
674+
if key_def is None:
675+
return
672676
label_name = label_names[axis]
673677
title = f"Edit {label_name}"
674678
prompt = f"New {label_name}:"
675-
plot_config = self._plot_customizer.get_plot_config()
676-
current_label = plot_config.x_label() if axis == "x" else plot_config.y_label()
679+
labels = self._x_labels if axis == "x" else self._y_labels
680+
current_label = labels.get(key_def.key)
677681
if current_label is None:
678682
current_widget = self._central_tab.currentWidget()
679683
if isinstance(current_widget, PlotWidget) and current_widget._figure.axes:
@@ -689,38 +693,30 @@ def _edit_axis_label(self, axis: str) -> None:
689693
if not accepted:
690694
return
691695
new_label: str | None = new_label_text or None
692-
if axis == "x":
693-
plot_config.set_x_label(new_label)
694-
else:
695-
plot_config.set_y_label(new_label)
696-
self._plot_customizer.update_plot_config(plot_config)
696+
labels[key_def.key] = new_label
697+
self.update_plot()
697698

698699
def _edit_title(self) -> None:
700+
key_def = self.getSelectedKey()
701+
if key_def is None:
702+
return
699703
title = "Edit title"
700-
plot_config = self._plot_customizer.get_plot_config()
701704
new_title, accepted = self._general_options.get_text_input(
702705
title,
703706
"New title:",
704-
plot_config.title(),
707+
self._titles.get(key_def.key, key_def.key),
705708
)
706709
if not accepted:
707710
return
708-
if new_title:
709-
plot_config.set_title(new_title)
710-
else:
711-
key_def = self.getSelectedKey()
712-
if key_def is None:
713-
return
714-
plot_config.set_title(key_def.key)
715-
self._plot_customizer.update_plot_config(plot_config)
711+
self._titles[key_def.key] = new_title or key_def.key
712+
self.update_plot()
716713

717714
@showWaitCursorWhileWaiting
718715
def keySelected(self) -> None:
719716
key_def = self.getSelectedKey()
720717
if key_def is None:
721718
self._show_no_data_message()
722719
return
723-
self._plot_customizer.switch_plot_config_history(key_def)
724720

725721
is_everest_specific_widget = key_def.metadata.get("data_origin") in {
726722
"everest_objectives",
@@ -835,9 +831,6 @@ def everest_available_widget_selection(
835831
self._prev_key_origin = key_def.metadata.get("data_origin")
836832
self.update_plot()
837833

838-
def toggle_customize_dialog(self) -> None:
839-
self._plot_customizer.toggle_customization_dialog()
840-
841834
def add_plot_widgets_from_plot_map(
842835
self, plot_map: dict[str, Callable[[], Plotter]]
843836
) -> None:

src/ert/gui/plotting/widgets/plot_widget.py

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from PyQt6.QtCore import QStringListModel, Qt
1818
from PyQt6.QtCore import pyqtSignal as Signal
1919
from PyQt6.QtCore import pyqtSlot as Slot
20-
from PyQt6.QtGui import QAction, QCursor
20+
from PyQt6.QtGui import QCursor
2121
from PyQt6.QtWidgets import (
2222
QComboBox,
2323
QToolTip,
@@ -26,7 +26,6 @@
2626
QWidgetAction,
2727
)
2828

29-
from ert.gui.icon_utils import load_icon
3029
from ert.gui.plotting.plot_api import EnsembleObject, PlotApiKeyDefinition
3130
from ert.gui.plotting.utils.plot_types import ObservationPlotLocations
3231

@@ -55,7 +54,6 @@ def plot(
5554

5655

5756
class CustomNavigationToolbar(NavigationToolbar2QT):
58-
customizationTriggered = Signal()
5957
layer_index_changed = Signal(int)
6058

6159
def __init__(
@@ -67,14 +65,6 @@ def __init__(
6765
) -> None:
6866
super().__init__(canvas, parent, coordinates) # type: ignore
6967

70-
gear = load_icon("edit.svg")
71-
customize_action = QAction(gear, "Customize", self)
72-
customize_action.setToolTip("Customize plot settings")
73-
customize_action.triggered.connect(self.customizationTriggered)
74-
customize_action.triggered.connect(
75-
lambda: self.logToolbarUsage(customize_action.text())
76-
)
77-
7868
layer_combobox = QComboBox()
7969
self._model = QStringListModel()
8070
layer_combobox.setModel(self._model)
@@ -84,10 +74,6 @@ def __init__(
8474
if str(action.text()).lower() == "subplots":
8575
self.removeAction(action)
8676

87-
if str(action.text()).lower() == "customize":
88-
self.insertAction(action, customize_action)
89-
self.removeAction(action)
90-
9177
# insert the layer widget before the coordinates widget
9278
if isinstance(action, QWidgetAction):
9379
self._layer_action = self.insertWidget(action, layer_combobox)
@@ -120,7 +106,6 @@ def updateLayerWidget(self, layers: int) -> None:
120106

121107

122108
class PlotWidget(QWidget):
123-
customizationTriggered = Signal()
124109
axisLabelEditRequested = Signal(str)
125110
titleEditRequested = Signal()
126111
layer_index_changed = Signal(int)
@@ -153,7 +138,6 @@ def __init__(
153138
vbox = QVBoxLayout()
154139
vbox.addWidget(self._canvas)
155140
self._toolbar = CustomNavigationToolbar(self._canvas, self)
156-
self._toolbar.customizationTriggered.connect(self.customizationTriggered)
157141
self._toolbar.layer_index_changed.connect(self.layer_index_changed)
158142
self.updateLayerWidget.connect(self._toolbar.updateLayerWidget)
159143
self.resetLayerWidget.connect(self._toolbar.resetLayerWidget)

tests/ert/unit_tests/gui/tools/plot/test_plot_window.py

Lines changed: 13 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,9 @@ def _create_plot_window_for_text_edit(
10391039
monkeypatch.setattr("ert.gui.plotting.plot_window.PlotApi", mock_plot_api_cls)
10401040
plot_window = PlotWindow(config_file="", ens_path=Path(), parent=None)
10411041
qtbot.addWidget(plot_window)
1042+
plot_window.getSelectedKey = MagicMock(
1043+
return_value=MagicMock(key="some_key", dimensionality=1, metadata={})
1044+
)
10421045
return plot_window
10431046

10441047

@@ -1086,12 +1089,8 @@ def test_that_sidebar_axis_label_edit_uses_configured_or_visible_label(
10861089
plot_window = _create_plot_window_for_text_edit(qtbot, monkeypatch)
10871090
get_text_input = MagicMock(return_value=("", False))
10881091
plot_window._general_options.get_text_input = get_text_input
1089-
plot_config = plot_window._plot_customizer.get_plot_config()
1090-
if axis == "x":
1091-
plot_config.set_x_label(configured_label)
1092-
else:
1093-
plot_config.set_y_label(configured_label)
1094-
plot_window._plot_customizer.update_plot_config(plot_config)
1092+
labels = plot_window._x_labels if axis == "x" else plot_window._y_labels
1093+
labels["some_key"] = configured_label
10951094
current_widget = plot_window._central_tab.currentWidget()
10961095
assert isinstance(current_widget, PlotWidget)
10971096
if visible_label is not None:
@@ -1140,36 +1139,19 @@ def test_that_axis_label_edit_updates_or_preserves_persistent_config(
11401139
plot_window = _create_plot_window_for_text_edit(qtbot, monkeypatch)
11411140
get_text_input = MagicMock(return_value=(new_label, accepted))
11421141
plot_window._general_options.get_text_input = get_text_input
1143-
plot_config = plot_window._plot_customizer.get_plot_config()
1144-
if axis == "x":
1145-
plot_config.set_x_label(current_label)
1146-
else:
1147-
plot_config.set_y_label(current_label)
1148-
plot_window._plot_customizer.update_plot_config(plot_config)
1142+
plot_window.update_plot = MagicMock()
1143+
labels = plot_window._x_labels if axis == "x" else plot_window._y_labels
1144+
labels["some_key"] = current_label
11491145

11501146
plot_window._edit_axis_label(axis)
11511147

11521148
expected_label = (new_label or None) if accepted else current_label
1153-
persisted_config = plot_window._plot_customizer.get_plot_config()
1154-
assert (
1155-
persisted_config.x_label() if axis == "x" else persisted_config.y_label()
1156-
) == expected_label
1149+
assert labels["some_key"] == expected_label
11571150
get_text_input.assert_called_once_with(
11581151
f"Edit {axis}-label", f"New {axis}-label:", current_label
11591152
)
11601153

11611154

1162-
def _create_plot_window_for_title_edit(
1163-
qtbot: QtBot,
1164-
monkeypatch: pytest.MonkeyPatch,
1165-
) -> PlotWindow:
1166-
plot_window = _create_plot_window_for_text_edit(qtbot, monkeypatch)
1167-
plot_window.getSelectedKey = MagicMock(
1168-
return_value=MagicMock(key="some_key", dimensionality=1, metadata={})
1169-
)
1170-
return plot_window
1171-
1172-
11731155
@pytest.mark.parametrize(
11741156
("dialog_value", "expected_title", "accepted"),
11751157
[
@@ -1190,19 +1172,15 @@ def test_that_title_edit_updates_or_preserves_persistent_config(
11901172
expected_title: str,
11911173
accepted: bool,
11921174
) -> None:
1193-
plot_window = _create_plot_window_for_title_edit(qtbot, monkeypatch)
1175+
plot_window = _create_plot_window_for_text_edit(qtbot, monkeypatch)
11941176
get_text_input = MagicMock(return_value=(dialog_value, accepted))
11951177
plot_window._general_options.get_text_input = get_text_input
11961178
plot_window.update_plot = MagicMock()
1197-
plot_window._plot_customizer._emit_changed_signal = MagicMock()
1198-
plot_config = plot_window._plot_customizer.get_plot_config()
1199-
plot_config.set_title("Existing title")
1200-
plot_window._plot_customizer.update_plot_config(plot_config)
1179+
plot_window._titles["some_key"] = "Existing title"
12011180

12021181
plot_window._edit_title()
12031182

1204-
persisted_config = plot_window._plot_customizer.get_plot_config()
1205-
assert persisted_config.title() == expected_title
1183+
assert plot_window._titles["some_key"] == expected_title
12061184
get_text_input.assert_called_once_with("Edit title", "New title:", "Existing title")
12071185

12081186

@@ -1258,9 +1236,7 @@ def test_that_clearing_custom_title_restores_key_title_when_rendering(
12581236
plot_window._general_options.get_text_input = MagicMock(return_value=("", True))
12591237
plot_window.update_plot()
12601238

1261-
plot_config = plot_window._plot_customizer.get_plot_config()
1262-
plot_config.set_title("Custom title")
1263-
plot_window._plot_customizer.update_plot_config(plot_config)
1239+
plot_window._titles["some_key"] = "Custom title"
12641240
plot_window._edit_title()
12651241

12661242
plot_widget = plot_window._central_tab.currentWidget()

0 commit comments

Comments
 (0)