Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions MDANSE_GUI/Src/MDANSE_GUI/TabbedWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,21 @@ def __init__(
self._tabs["Instruments"]._visualiser.instrument_details_changed.connect(
self._tabs["Actions"].update_action_after_instrument_change
)
self._tabs["Plot Holder"]._visualiser.current_tab_index.connect(
self._tabs["Plot Creator"]._visualiser.new_target_plot_index
)
self._tabs["Plot Holder"]._visualiser.current_tab_count.connect(
self._tabs["Plot Creator"]._visualiser.new_target_plot_count
)
self._tabs["Plot Holder"]._visualiser.datasets_in_plot.connect(
self._tabs["Plot Creator"]._visualiser.new_dataset_count_in_target
)
self._tabs["Plot Holder"]._visualiser.plot_widget_type.connect(
self._tabs["Plot Creator"]._visualiser.new_plot_widget_type
)
self._tabs["Plot Holder"].connect_external_view(
self._tabs["Plot Creator"]._visualiser.preview_table
)
# connect signal to the tab
self.signal_recent_trajectory_file.connect(
self._tabs["Trajectories"].load_trajectory
Expand Down
13 changes: 11 additions & 2 deletions MDANSE_GUI/Src/MDANSE_GUI/Tabs/PlotTab.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from MDANSE_GUI.Widgets.PlotSettingsDialog import PlotSettingsEditor

if TYPE_CHECKING:
from qtpy.QtWidgets import QDialog, QWidget
from qtpy.QtWidgets import QAbstractItemView, QDialog, QWidget

from MDANSE_GUI.Session.Session import Session

Expand Down Expand Up @@ -66,6 +66,12 @@ def __init__(self, *args, **kwargs):
)
self.matplotlib_dialog.values_changed.connect(self._visualiser.update_plots)
self._core.add_button("Change matplotlib settings", self.edit_matplotlib)
self.connected_views = [self._view]

def connect_external_view(self, new_view: QAbstractItemView):
if new_view not in self.connected_views:
self.connected_views.append(new_view)
new_view.setModel(self.model)

def launch_dialog(self, dialog: QDialog) -> None:
if dialog.isVisible():
Expand Down Expand Up @@ -127,7 +133,10 @@ def accept_external_data(self, data_model):
LOG.error(f"Visualiser failed to plot data: {e2}")
else:
self.tab_notification()
self._visualiser.send_plot_info()

@Slot(int)
def switch_model(self, tab_id):
self._view.setModel(self.model)
for view in self.connected_views:
view.setModel(self.model)
self._visualiser.send_plot_info()
96 changes: 81 additions & 15 deletions MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/DataPlotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

from qtpy.QtCore import Signal, Slot
from qtpy.QtWidgets import (
QGroupBox,
QHBoxLayout,
QLabel,
QMessageBox,
QPushButton,
QTableView,
Expand Down Expand Up @@ -47,31 +49,95 @@ class DataPlotter(QWidget):

def __init__(self, *args, unit_lookup=None, **kwargs):
super().__init__(*args, **kwargs)

self.tab_index, self.tab_count = 0, 1
self.dataset_count = 0
self.plotter_type = "PlotWidget"
self._unit_lookup = unit_lookup
layout = QVBoxLayout(self)
button_bar = QWidget(self)
button_layout = QHBoxLayout(button_bar)
control_bar = QWidget(self)
bar_layout = QHBoxLayout(control_bar)
self._selection_viewer = QTableView(self)
layout.addWidget(self._selection_viewer)
layout.addWidget(button_bar)
buttons = [
("Plot Data", self.plot_data),
("Clear", self.clear),
("New Plot", self.new_plot),
("New Data View (Text)", self.new_text),
]
for name, function in buttons:
button = QPushButton(name, button_bar)
button_layout.addWidget(button)
if function is not None:
button.clicked.connect(function)
layout.addWidget(control_bar)
button_bar = self.create_buttons()
bar_layout.addWidget(button_bar)
plotter_preview = self.create_preview()
bar_layout.addWidget(plotter_preview)
self._model = PlottingContext(
unit_lookup=self._unit_lookup,
)
self._selection_viewer.setModel(self._model)
self.hide_columns()

def create_buttons(self) -> QWidget:
button_bar = QWidget(self)
button_layout = QVBoxLayout(button_bar)
button_groups = {
"Empty plot creation": [
("New empty plot", self.new_plot),
("New empty text view", self.new_text),
],
"Current data selection": [
("Send data to plotter", self.plot_data),
("Clear data selection", self.clear),
],
}
for group_name, buttons in button_groups.items():
subgroup = QGroupBox(group_name, button_bar)
sublayout = QVBoxLayout(subgroup)
for name, function in buttons:
button = QPushButton(name, button_bar)
sublayout.addWidget(button)
if function is not None:
button.clicked.connect(function)
button_layout.addWidget(subgroup)
return button_bar

def create_preview(self) -> QWidget:
previewer = QWidget(self)
previewer_layout = QVBoxLayout(previewer)
self.target_label = QLabel("Target plot in next tab.")
self.target_label.setWordWrap(True)
previewer_layout.addWidget(self.target_label)
info_label = QLabel(
f"Contents of the currently selected {self.plotter_type} in the next tab:"
)
previewer_layout.addWidget(info_label)
self.preview_table = QTableView(previewer)
previewer_layout.addWidget(self.preview_table)
self.update_target_plot_label()
return previewer

def update_target_plot_label(self):
self.target_label.setText(
"Datasets listed above will be sent to the <b>Plot Holder</b> tab.<br>"
f"They will appear in tab {self.tab_index + 1} out of {self.tab_count}.<br>"
f"It is a {self.plotter_type}, currently containing {self.dataset_count} datasets."
)
for col_num in range(4, 10):
self.preview_table.hideColumn(col_num)
self.preview_table.resizeColumnsToContents()

@Slot(int)
def new_target_plot_index(self, new_index: int):
self.tab_index = new_index
self.update_target_plot_label()

@Slot(int)
def new_target_plot_count(self, new_count: int):
self.tab_count = new_count
self.update_target_plot_label()

@Slot(int)
def new_dataset_count_in_target(self, new_dataset_count: int):
self.dataset_count = new_dataset_count
self.update_target_plot_label()

@Slot(str)
def new_plot_widget_type(self, new_plot_widget_type: str):
self.plotter_type = new_plot_widget_type
self.update_target_plot_label()

@Slot(object)
def add_dataset(self, dataset: SingleDataset):
"""Append a dataset to the current model."""
Expand Down
19 changes: 17 additions & 2 deletions MDANSE_GUI/Src/MDANSE_GUI/Tabs/Visualisers/PlotHolder.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class PlotHolder(QTabWidget):

error = Signal(str)
new_entry = Signal()
current_tab_index = Signal(int)
current_tab_count = Signal(int)
datasets_in_plot = Signal(int)
plot_widget_type = Signal(str)

def __init__(self, *args, unit_lookup=None, **kwargs):
super().__init__(*args, **kwargs)
Expand Down Expand Up @@ -75,6 +79,7 @@ def new_plot(self, tab_name: str) -> int:
self._plotter.append(plotter)
self.setCurrentIndex(tab_id)
self.new_entry.emit()
self.send_plot_info()
return tab_id

@Slot(str)
Expand All @@ -91,6 +96,7 @@ def new_text(self, ignored_name: str) -> int:
self._plotter.append(plotter)
self.setCurrentIndex(tab_id)
self.new_entry.emit()
self.send_plot_info()
return tab_id

@Slot(int)
Expand All @@ -108,9 +114,10 @@ def clean_up_closed_tab(self, tab_id: int):
self._current_id = valid_id_values[0]
self.setCurrentIndex(self._current_id)
self.removeTab(tab_id)
self.send_plot_info()

@property
def model(self):
def model(self) -> PlottingContext:
tab_id = self.currentIndex()
try:
pc = self._context[tab_id]
Expand All @@ -122,7 +129,7 @@ def model(self):
return pc

@property
def plotter(self):
def plotter(self) -> DataWidget:
tab_id = self.currentIndex()
try:
return self._plotter[tab_id]
Expand Down Expand Up @@ -164,3 +171,11 @@ def update_plot(self, plot_number: int):
except Exception:
LOG.error("Plotting failed: %s", traceback.format_exc())
plotter.plot_blank()
else:
self.send_plot_info()

def send_plot_info(self):
self.current_tab_count.emit(len(self._plotter))
self.current_tab_index.emit(self.currentIndex())
self.datasets_in_plot.emit(self.model.rowCount())
self.plot_widget_type.emit(type(self.plotter).__name__)
Loading