diff --git a/Framework/PythonInterface/test/python/mantid/plots/plotfunctionsTest.py b/Framework/PythonInterface/test/python/mantid/plots/plotfunctionsTest.py index 75bbf1d5e059e2c2e0dad1c0f265e337187e91ea..cff911f8752e3f43034ef312318d4f41fb25f5da 100644 --- a/Framework/PythonInterface/test/python/mantid/plots/plotfunctionsTest.py +++ b/Framework/PythonInterface/test/python/mantid/plots/plotfunctionsTest.py @@ -9,8 +9,8 @@ import unittest import mantid.api import mantid.plots.plotfunctions as funcs from mantid.kernel import config -from mantid.simpleapi import CreateWorkspace, DeleteWorkspace, CreateMDHistoWorkspace,\ - ConjoinWorkspaces, AddTimeSeriesLog +from mantid.simpleapi import (CreateWorkspace, CreateEmptyTableWorkspace, DeleteWorkspace, + CreateMDHistoWorkspace, ConjoinWorkspaces, AddTimeSeriesLog) @@ -116,6 +116,19 @@ class PlotFunctionsTest(unittest.TestCase): funcs.pcolormesh(ax, self.ws_MD_2d) funcs.pcolorfast(ax, self.ws2d_point_uneven, vmin=-1) + def test_1d_plots_with_unplottable_type_raises_attributeerror(self): + table = CreateEmptyTableWorkspace() + _, ax = plt.subplots() + self.assertRaises(AttributeError, funcs.plot, ax, table, wkspIndex=0) + self.assertRaises(AttributeError, funcs.errorbar, ax, table, wkspIndex=0) + + def test_2d_plots_with_unplottable_type_raises_attributeerror(self): + table = CreateEmptyTableWorkspace() + _, ax = plt.subplots() + self.assertRaises(AttributeError, funcs.pcolor, ax, table) + self.assertRaises(AttributeError, funcs.pcolormesh, ax, table) + self.assertRaises(AttributeError, funcs.pcolorfast, ax, table) + if __name__ == '__main__': unittest.main() diff --git a/qt/applications/workbench/workbench/plotting/functions.py b/qt/applications/workbench/workbench/plotting/functions.py index 9a30c4441d46ee6659d5ffa7b4f548d39aface94..fa68140fa08c042af3ef5ae4616cbb76269328e0 100644 --- a/qt/applications/workbench/workbench/plotting/functions.py +++ b/qt/applications/workbench/workbench/plotting/functions.py @@ -24,6 +24,7 @@ import math # 3rd party imports from mantid.api import AnalysisDataService, MatrixWorkspace +from mantid.kernel import Logger import matplotlib.pyplot as plt from mantidqt.py3compat import is_text_string from mantidqt.dialogs.spectraselectordialog import get_spectra_selection @@ -41,6 +42,7 @@ DEFAULT_COLORMAP = 'viridis' # See https://matplotlib.org/api/_as_gen/matplotlib.figure.SubplotParams.html#matplotlib.figure.SubplotParams SUBPLOT_WSPACE = 0.5 SUBPLOT_HSPACE = 0.5 +LOGGER = Logger("workspace.plotting.functions") # ----------------------------------------------------------------------------- @@ -104,7 +106,7 @@ def figure_title(workspaces, fig_num): def plot_from_names(names, errors, overplot, fig=None): """ Given a list of names of workspaces, raise a dialog asking for the - a selection of what to plot and then plot it + a selection of what to plot and then plot it. :param names: A list of workspace names :param errors: If true then error bars will be plotted on the points @@ -114,7 +116,12 @@ def plot_from_names(names, errors, overplot, fig=None): :return: The figure containing the plot or None if selection was cancelled """ workspaces = AnalysisDataService.Instance().retrieveWorkspaces(names, unrollGroups=True) - selection = get_spectra_selection(workspaces) + try: + selection = get_spectra_selection(workspaces) + except Exception as exc: + LOGGER.warning(format(str(exc))) + selection = None + if selection is None: return None @@ -180,8 +187,12 @@ def pcolormesh_from_names(names, fig=None): :param fig: An optional figure to contain the new plots. Its current contents will be cleared :returns: The figure containing the plots """ - return pcolormesh(AnalysisDataService.retrieveWorkspaces(names, unrollGroups=True), - fig=fig) + try: + return pcolormesh(AnalysisDataService.retrieveWorkspaces(names, unrollGroups=True), + fig=fig) + except Exception as exc: + LOGGER.warning(format(str(exc))) + return None def pcolormesh(workspaces, fig=None): @@ -260,10 +271,25 @@ def plotSpectrum(workspaces, indices, distribution=None, error_bars=False, # ----------------------------------------------------------------------------- # 'Private' Functions # ----------------------------------------------------------------------------- -def _raise_if_not_sequence(seq, seq_name): - accepted_types = [list, tuple] - if type(seq) not in accepted_types: +def _raise_if_not_sequence(value, seq_name, element_type=None): + """ + Raise a ValueError if the given object is not a sequence + + :param value: The value object to validate + :param seq_name: The variable name of the sequence for the error message + :param element_type: An optional type to provide to check that each element + is an instance of this type + :raises ValueError: if the conditions are not met + """ + accepted_types = (list, tuple) + if type(value) not in accepted_types: raise ValueError("{} should be a list or tuple".format(seq_name)) + if element_type is not None: + def raise_if_not_type(x): + if not isinstance(x, element_type): + raise ValueError("Unexpected type: '{}'".format(x.__class__.__name__)) + + map(raise_if_not_type, value) def _validate_plot_inputs(workspaces, spectrum_nums, wksp_indices): @@ -272,8 +298,7 @@ def _validate_plot_inputs(workspaces, spectrum_nums, wksp_indices): raise ValueError("Both spectrum_nums and wksp_indices supplied. " "Please supply only 1.") - if not isinstance(workspaces, MatrixWorkspace): - _raise_if_not_sequence(workspaces, 'Workspaces') + _raise_if_not_sequence(workspaces, 'workspaces', MatrixWorkspace) if spectrum_nums is not None: _raise_if_not_sequence(spectrum_nums, 'spectrum_nums') @@ -284,8 +309,7 @@ def _validate_plot_inputs(workspaces, spectrum_nums, wksp_indices): def _validate_pcolormesh_inputs(workspaces): """Raises a ValueError if any arguments have the incorrect types""" - if not isinstance(workspaces, MatrixWorkspace): - _raise_if_not_sequence(workspaces, 'Workspaces') + _raise_if_not_sequence(workspaces, 'workspaces', MatrixWorkspace) def _create_subplots(nplots, fig=None): diff --git a/qt/applications/workbench/workbench/plotting/test/test_functions.py b/qt/applications/workbench/workbench/plotting/test/test_functions.py index 420134c43697949c1512f7cf3d1612e6f7e9c950..a1c11d316eaf0a2860315f7c827485ec75821ce0 100644 --- a/qt/applications/workbench/workbench/plotting/test/test_functions.py +++ b/qt/applications/workbench/workbench/plotting/test/test_functions.py @@ -155,6 +155,22 @@ class FunctionsTest(TestCase): self.assertEqual(fig, target_fig) self.assertEqual(1, len(fig.gca().collections)) + # ------------- Failure tests ------------- + + def test_plot_from_names_with_non_plottable_workspaces_returns_None(self): + table = WorkspaceFactory.Instance().createTable() + table_name = 'test_plot_from_names_with_non_plottable_workspaces_returns_None' + AnalysisDataService.Instance().addOrReplace(table_name, table) + result = plot_from_names([table_name], errors=False, overplot=False) + self.assertTrue(result is None) + + def test_pcolormesh_from_names_with_non_plottable_workspaces_returns_None(self): + table = WorkspaceFactory.Instance().createTable() + table_name = 'test_pcolormesh_from_names_with_non_plottable_workspaces_returns_None' + AnalysisDataService.Instance().addOrReplace(table_name, table) + result = pcolormesh_from_names([table_name]) + self.assertTrue(result is None) + # ------------- Private ------------------- def _do_plot_from_names_test(self, get_spectra_selection_mock, expected_labels, wksp_indices, errors, overplot, target_fig=None): @@ -178,4 +194,4 @@ class FunctionsTest(TestCase): if __name__ == '__main__': - main(buffer=False, verbosity=2) + main() diff --git a/qt/python/mantidqt/dialogs/test/test_spectraselectiondialog.py b/qt/python/mantidqt/dialogs/test/test_spectraselectiondialog.py index fbcd7f50e4decc9b2ece8721c719a7dd9e8617f1..9c6ebcae4ec2f53c50dc6f15165d8120d0b63285 100644 --- a/qt/python/mantidqt/dialogs/test/test_spectraselectiondialog.py +++ b/qt/python/mantidqt/dialogs/test/test_spectraselectiondialog.py @@ -28,7 +28,7 @@ from qtpy.QtWidgets import QDialog, QDialogButtonBox # local imports from mantidqt.utils.qt.test import requires_qapp -from mantidqt.dialogs.spectraselectordialog import (get_spectra_selection, parse_selection_str, \ +from mantidqt.dialogs.spectraselectordialog import (get_spectra_selection, parse_selection_str, SpectraSelectionDialog) @@ -43,7 +43,7 @@ class SpectraSelectionDialogTest(unittest.TestCase): self.__class__._single_spec_ws = WorkspaceFactory.Instance().create("Workspace2D", NVectors=1, XLength=1, YLength=1) self.__class__._multi_spec_ws = WorkspaceFactory.Instance().create("Workspace2D", NVectors=200, - XLength=1, YLength=1) + XLength=1, YLength=1) def test_initial_dialog_setup(self): workspaces = [self._multi_spec_ws]