Skip to content

Commit 8474240

Browse files
DespiixjclarkeSTFCpre-commit-ci[bot]
authored
Surface Plotting from Multiple Single-Spectrum Workspaces (#38599)
* Enable Plot All and Okay button * If any workspace contains only 1 spectra then set default value to 1. and minor file reformat * Fix plotting * Add release note * Adjust buttons to correct enable and disable + Adjust Test * Adjust function based on review * Remove Hardcoded "1" Set the default value as the first valid spectrum number * Fix plotting multiple wireframe workspaces * Clean up * Release Note Update * Enable `Plot_All` for Contour plots * Handle Error * Handle Error * If there is already a valid selection (wksp_indices or spectra), just ski * Update docs/source/release/v6.12.0/Workbench/New_features/38171.rst Co-authored-by: James Clarke <139879523+jclarkeSTFC@users.noreply.github.com> * Update docs/source/release/v6.12.0/Workbench/New_features/38171.rst Co-authored-by: James Clarke <139879523+jclarkeSTFC@users.noreply.github.com> * Changes based on suggestions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Delete duplicate code * Delete duplicate code --------- Co-authored-by: James Clarke <139879523+jclarkeSTFC@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 727a603 commit 8474240

File tree

4 files changed

+75
-26
lines changed

4 files changed

+75
-26
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- Enabled surface and contour plotting in the `Plot Advanced` dialog when multiple single-spectrum workspaces are selected.
2+
- Fixed a bug where selecting multiple workspaces in the ADS and plotting a wireframe would only result in one of the workspaces being plotted.

qt/python/mantidqt/mantidqt/dialogs/spectraselectordialog.py

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,35 @@ def __init__(self, workspaces, parent=None, show_colorfill_btn=False, overplot=F
100100
self._on_specnums_changed()
101101
self._on_wkspindices_changed()
102102

103+
# Check if workspace only has a single spectra, if true set it as first valid spectrum number
104+
def update_spectrum_number_text(self):
105+
if self.selection and (
106+
(self.selection.wksp_indices and len(self.selection.wksp_indices) > 0)
107+
or (self.selection.spectra and len(self.selection.spectra) > 0)
108+
):
109+
return
110+
111+
if not self._ui.specNums.text():
112+
for ws in self._workspaces:
113+
if ws.getNumberHistograms() == 1:
114+
spectrum_number = ws.getSpectrum(0).getSpectrumNo()
115+
self._ui.specNums.setText(str(spectrum_number))
116+
self._parse_spec_nums()
117+
break
118+
103119
def on_ok_clicked(self):
120+
self.update_spectrum_number_text()
121+
122+
if self.selection is None:
123+
QMessageBox.warning(self, "Invalid Input", "Please enter a valid workspace index or spectrum number.")
124+
return
125+
104126
if self._check_number_of_plots(self.selection):
105127
self.accept()
106128

107129
def on_plot_all_clicked(self):
130+
self.update_spectrum_number_text()
131+
108132
selection = SpectraSelection(self._workspaces)
109133
selection.spectra = self._plottable_spectra
110134
selection.plot_type = self._ui.plotType.currentIndex()
@@ -252,21 +276,29 @@ def _on_specnums_changed(self):
252276
ui.wkspIndices.clear()
253277
ui.wkspIndicesValid.hide()
254278

255-
self._parse_spec_nums()
256-
ui.specNumsValid.setVisible(not self._is_input_valid())
257-
if self._is_input_valid() or ui.specNums.text() == "":
258-
ui.specNumsValid.setVisible(False)
259-
ui.specNumsValid.setToolTip("")
260-
elif ui.plotType.currentText() == SURFACE or ui.plotType.currentText() == CONTOUR:
279+
try:
280+
self._parse_spec_nums()
281+
except Exception as e:
282+
logger.error(f"Error parsing spectrum numbers: {e}")
283+
ui.specNumsValid.setToolTip("Invalid spectrum number input.")
261284
ui.specNumsValid.setVisible(True)
262-
ui.specNumsValid.setToolTip("Enter one spectrum number in " + ui.specNums.placeholderText())
285+
ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)
286+
287+
spectrum_numbers = [ws.getSpectrumNumbers() for ws in self._workspaces]
288+
unique_spectra = {tuple(numbers) for numbers in spectrum_numbers}
289+
290+
if len(unique_spectra) > 1:
291+
ui.specNums.setEnabled(False)
292+
ui.specNumsValid.setToolTip("Spectrum numbers differ across workspaces. Use 'Plot All' or workspace indices instead.")
263293
else:
264-
ui.specNumsValid.setVisible(True)
265-
ui.specNumsValid.setToolTip("Not in " + ui.specNums.placeholderText())
294+
ui.specNums.setEnabled(True)
295+
ui.specNumsValid.setToolTip("")
296+
297+
ui.specNumsValid.setVisible(not self._is_input_valid())
266298
ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(self._is_input_valid())
267299

268300
if self._advanced:
269-
ui.advanced_options_widget._validate_custom_logs(self._ui.advanced_options_widget.ui.custom_log_line_edit.text())
301+
ui.advanced_options_widget._validate_custom_logs(ui.advanced_options_widget.ui.custom_log_line_edit.text())
270302

271303
def _on_plot_type_changed(self, new_index):
272304
if self._overplot:
@@ -290,7 +322,8 @@ def _on_plot_type_changed(self, new_index):
290322
if self._ui.advanced_options_widget.ui.plot_axis_label_line_edit.text() == WORKSPACE_NAME:
291323
self._ui.advanced_options_widget.ui.plot_axis_label_line_edit.setText(WORKSPACE_REFERENCE_NUMBER)
292324

293-
self._ui.buttonBox.button(QDialogButtonBox.YesToAll).setEnabled(False)
325+
self._ui.buttonBox.button(QDialogButtonBox.YesToAll).setEnabled(True)
326+
294327
else:
295328
self._ui.advanced_options_widget.ui.error_bars_check_box.setEnabled(True)
296329
self._ui.advanced_options_widget.ui.plot_axis_label_line_edit.setEnabled(False)

qt/python/mantidqt/mantidqt/dialogs/test/test_spectraselectiondialog.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,17 +281,17 @@ def test_ok_button_disabled_when_custom_log_values_contains_decreasing_values(se
281281
ssd._ui.advanced_options_widget.ui.custom_log_line_edit.setText("2,1,3")
282282
self.assertFalse(ssd._ui.buttonBox.button(QDialogButtonBox.Ok).isEnabled())
283283

284-
def test_plot_all_button_disabled_when_plot_type_is_surface(self):
284+
def test_plot_all_button_enabled_when_plot_type_is_surface(self):
285285
workspaces = [self._single_spec_ws] * 3
286286
ssd = SpectraSelectionDialog(workspaces, advanced=True)
287287
ssd._ui.plotType.setCurrentIndex(3)
288-
self.assertFalse(ssd._ui.buttonBox.button(QDialogButtonBox.YesToAll).isEnabled())
288+
self.assertTrue(ssd._ui.buttonBox.button(QDialogButtonBox.YesToAll).isEnabled())
289289

290-
def test_plot_all_button_disabled_when_plot_type_is_contour(self):
290+
def test_plot_all_button_enabled_when_plot_type_is_contour(self):
291291
workspaces = [self._single_spec_ws] * 3
292292
ssd = SpectraSelectionDialog(workspaces, advanced=True)
293293
ssd._ui.plotType.setCurrentIndex(4)
294-
self.assertFalse(ssd._ui.buttonBox.button(QDialogButtonBox.YesToAll).isEnabled())
294+
self.assertTrue(ssd._ui.buttonBox.button(QDialogButtonBox.YesToAll).isEnabled())
295295

296296
def test_ok_button_disabled_when_plot_type_is_surface_and_more_than_one_spectrum_number_entered(self):
297297
workspaces = [self._multi_spec_ws] * 3

qt/python/mantidqt/mantidqt/plotting/functions.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
from mantid.kernel import Logger, ConfigService
2424
from mantid.plots.datafunctions import add_colorbar_label
25-
from mantid.plots.utility import get_single_workspace_log_value
25+
from mantid.plots.utility import get_single_workspace_log_value, legend_set_draggable
2626
from mantidqt.plotting.figuretype import figure_type, FigureType
2727
from mantidqt.dialogs.spectraselectorutils import get_spectra_selection
2828
from mantid.api import IMDHistoWorkspace
@@ -365,18 +365,32 @@ def plot_surface(workspaces, fig=None):
365365
@manage_workspace_names
366366
def plot_wireframe(workspaces, fig=None):
367367
import matplotlib.pyplot as plt
368+
from matplotlib import colormaps
368369

369-
for ws in workspaces:
370-
if fig:
371-
fig.clf()
372-
ax = fig.add_subplot(111, projection="mantid3d")
373-
else:
374-
fig, ax = plt.subplots(subplot_kw={"projection": "mantid3d"})
370+
cmap = colormaps["tab10"]
371+
colors = [cmap(i / max(1, len(workspaces) - 1)) for i in range(len(workspaces))]
375372

376-
fig.set_layout_engine(layout="tight")
377-
ax.plot_wireframe(ws)
378-
ax.set_title(ws.name())
379-
fig.show()
373+
if fig:
374+
fig.clf()
375+
ax = fig.add_subplot(111, projection="mantid3d")
376+
else:
377+
fig, ax = plt.subplots(subplot_kw={"projection": "mantid3d"})
378+
379+
for i, ws in enumerate(workspaces):
380+
try:
381+
ax.plot_wireframe(ws, color=colors[i], label=ws.name())
382+
except Exception as e:
383+
LOGGER.error(f"Failed to plot workspace {ws.name()}: {e}")
384+
385+
if len(workspaces) > 1:
386+
legend = ax.legend(loc="upper right", title="Workspaces")
387+
legend_set_draggable(legend, True)
388+
389+
workspace_names = ", ".join(ws.name() for ws in workspaces)
390+
ax.set_title(f"Wireframe Plot: {workspace_names}")
391+
392+
fig.set_layout_engine(layout="tight")
393+
fig.show()
380394

381395
return fig
382396

0 commit comments

Comments
 (0)