Skip to content

Commit

Permalink
Surface Plotting from Multiple Single-Spectrum Workspaces (#38599)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>

* Update docs/source/release/v6.12.0/Workbench/New_features/38171.rst

Co-authored-by: James Clarke <[email protected]>

* 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 <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 27, 2025
1 parent 727a603 commit 8474240
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 26 deletions.
2 changes: 2 additions & 0 deletions docs/source/release/v6.12.0/Workbench/New_features/38171.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Enabled surface and contour plotting in the `Plot Advanced` dialog when multiple single-spectrum workspaces are selected.
- Fixed a bug where selecting multiple workspaces in the ADS and plotting a wireframe would only result in one of the workspaces being plotted.
55 changes: 44 additions & 11 deletions qt/python/mantidqt/mantidqt/dialogs/spectraselectordialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,35 @@ def __init__(self, workspaces, parent=None, show_colorfill_btn=False, overplot=F
self._on_specnums_changed()
self._on_wkspindices_changed()

# Check if workspace only has a single spectra, if true set it as first valid spectrum number
def update_spectrum_number_text(self):
if self.selection and (
(self.selection.wksp_indices and len(self.selection.wksp_indices) > 0)
or (self.selection.spectra and len(self.selection.spectra) > 0)
):
return

if not self._ui.specNums.text():
for ws in self._workspaces:
if ws.getNumberHistograms() == 1:
spectrum_number = ws.getSpectrum(0).getSpectrumNo()
self._ui.specNums.setText(str(spectrum_number))
self._parse_spec_nums()
break

def on_ok_clicked(self):
self.update_spectrum_number_text()

if self.selection is None:
QMessageBox.warning(self, "Invalid Input", "Please enter a valid workspace index or spectrum number.")
return

if self._check_number_of_plots(self.selection):
self.accept()

def on_plot_all_clicked(self):
self.update_spectrum_number_text()

selection = SpectraSelection(self._workspaces)
selection.spectra = self._plottable_spectra
selection.plot_type = self._ui.plotType.currentIndex()
Expand Down Expand Up @@ -252,21 +276,29 @@ def _on_specnums_changed(self):
ui.wkspIndices.clear()
ui.wkspIndicesValid.hide()

self._parse_spec_nums()
ui.specNumsValid.setVisible(not self._is_input_valid())
if self._is_input_valid() or ui.specNums.text() == "":
ui.specNumsValid.setVisible(False)
ui.specNumsValid.setToolTip("")
elif ui.plotType.currentText() == SURFACE or ui.plotType.currentText() == CONTOUR:
try:
self._parse_spec_nums()
except Exception as e:
logger.error(f"Error parsing spectrum numbers: {e}")
ui.specNumsValid.setToolTip("Invalid spectrum number input.")
ui.specNumsValid.setVisible(True)
ui.specNumsValid.setToolTip("Enter one spectrum number in " + ui.specNums.placeholderText())
ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False)

spectrum_numbers = [ws.getSpectrumNumbers() for ws in self._workspaces]
unique_spectra = {tuple(numbers) for numbers in spectrum_numbers}

if len(unique_spectra) > 1:
ui.specNums.setEnabled(False)
ui.specNumsValid.setToolTip("Spectrum numbers differ across workspaces. Use 'Plot All' or workspace indices instead.")
else:
ui.specNumsValid.setVisible(True)
ui.specNumsValid.setToolTip("Not in " + ui.specNums.placeholderText())
ui.specNums.setEnabled(True)
ui.specNumsValid.setToolTip("")

ui.specNumsValid.setVisible(not self._is_input_valid())
ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(self._is_input_valid())

if self._advanced:
ui.advanced_options_widget._validate_custom_logs(self._ui.advanced_options_widget.ui.custom_log_line_edit.text())
ui.advanced_options_widget._validate_custom_logs(ui.advanced_options_widget.ui.custom_log_line_edit.text())

def _on_plot_type_changed(self, new_index):
if self._overplot:
Expand All @@ -290,7 +322,8 @@ def _on_plot_type_changed(self, new_index):
if self._ui.advanced_options_widget.ui.plot_axis_label_line_edit.text() == WORKSPACE_NAME:
self._ui.advanced_options_widget.ui.plot_axis_label_line_edit.setText(WORKSPACE_REFERENCE_NUMBER)

self._ui.buttonBox.button(QDialogButtonBox.YesToAll).setEnabled(False)
self._ui.buttonBox.button(QDialogButtonBox.YesToAll).setEnabled(True)

else:
self._ui.advanced_options_widget.ui.error_bars_check_box.setEnabled(True)
self._ui.advanced_options_widget.ui.plot_axis_label_line_edit.setEnabled(False)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,17 +281,17 @@ def test_ok_button_disabled_when_custom_log_values_contains_decreasing_values(se
ssd._ui.advanced_options_widget.ui.custom_log_line_edit.setText("2,1,3")
self.assertFalse(ssd._ui.buttonBox.button(QDialogButtonBox.Ok).isEnabled())

def test_plot_all_button_disabled_when_plot_type_is_surface(self):
def test_plot_all_button_enabled_when_plot_type_is_surface(self):
workspaces = [self._single_spec_ws] * 3
ssd = SpectraSelectionDialog(workspaces, advanced=True)
ssd._ui.plotType.setCurrentIndex(3)
self.assertFalse(ssd._ui.buttonBox.button(QDialogButtonBox.YesToAll).isEnabled())
self.assertTrue(ssd._ui.buttonBox.button(QDialogButtonBox.YesToAll).isEnabled())

def test_plot_all_button_disabled_when_plot_type_is_contour(self):
def test_plot_all_button_enabled_when_plot_type_is_contour(self):
workspaces = [self._single_spec_ws] * 3
ssd = SpectraSelectionDialog(workspaces, advanced=True)
ssd._ui.plotType.setCurrentIndex(4)
self.assertFalse(ssd._ui.buttonBox.button(QDialogButtonBox.YesToAll).isEnabled())
self.assertTrue(ssd._ui.buttonBox.button(QDialogButtonBox.YesToAll).isEnabled())

def test_ok_button_disabled_when_plot_type_is_surface_and_more_than_one_spectrum_number_entered(self):
workspaces = [self._multi_spec_ws] * 3
Expand Down
36 changes: 25 additions & 11 deletions qt/python/mantidqt/mantidqt/plotting/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from mantid.kernel import Logger, ConfigService
from mantid.plots.datafunctions import add_colorbar_label
from mantid.plots.utility import get_single_workspace_log_value
from mantid.plots.utility import get_single_workspace_log_value, legend_set_draggable
from mantidqt.plotting.figuretype import figure_type, FigureType
from mantidqt.dialogs.spectraselectorutils import get_spectra_selection
from mantid.api import IMDHistoWorkspace
Expand Down Expand Up @@ -365,18 +365,32 @@ def plot_surface(workspaces, fig=None):
@manage_workspace_names
def plot_wireframe(workspaces, fig=None):
import matplotlib.pyplot as plt
from matplotlib import colormaps

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

fig.set_layout_engine(layout="tight")
ax.plot_wireframe(ws)
ax.set_title(ws.name())
fig.show()
if fig:
fig.clf()
ax = fig.add_subplot(111, projection="mantid3d")
else:
fig, ax = plt.subplots(subplot_kw={"projection": "mantid3d"})

for i, ws in enumerate(workspaces):
try:
ax.plot_wireframe(ws, color=colors[i], label=ws.name())
except Exception as e:
LOGGER.error(f"Failed to plot workspace {ws.name()}: {e}")

if len(workspaces) > 1:
legend = ax.legend(loc="upper right", title="Workspaces")
legend_set_draggable(legend, True)

workspace_names = ", ".join(ws.name() for ws in workspaces)
ax.set_title(f"Wireframe Plot: {workspace_names}")

fig.set_layout_engine(layout="tight")
fig.show()

return fig

Expand Down

0 comments on commit 8474240

Please sign in to comment.