diff --git a/docs/source/release/v5.0.0/muon.rst b/docs/source/release/v5.0.0/muon.rst index c00c85ce5e990532c81c1afffab84d7d90e9cfae..be69dcf9f9044263f405344c062164237d765911 100644 --- a/docs/source/release/v5.0.0/muon.rst +++ b/docs/source/release/v5.0.0/muon.rst @@ -12,6 +12,7 @@ Algorithms Bug Fixes --------- - :ref:`LoadPSIMuonBin <algm-LoadPSIMuonBin>` can produce an empty dead time table, the time data is offset such that the start of thepulse is at time zero. The start and end date logs have been fixed and if no group name is present a default is generated. +- The increment arrow no longer gives a spurious warning that the requested run exceeds the current run. Muon Analysis 2 and Frequency Domain Interfaces diff --git a/qt/applications/workbench/workbench/plugins/workspacewidget.py b/qt/applications/workbench/workbench/plugins/workspacewidget.py index 4af40c31a6002720ab813e5021c68c3972e0cc97..c9a1f9110c3e861c1c3fd511f33043a8c91c5de1 100644 --- a/qt/applications/workbench/workbench/plugins/workspacewidget.py +++ b/qt/applications/workbench/workbench/plugins/workspacewidget.py @@ -231,7 +231,7 @@ class WorkspaceWidget(PluginWidget): TableWorkspaceDisplay.supports(ws) self._do_show_data([name]) except ValueError: - if ws.blocksize() == 1: + if hasattr(ws, 'blocksize') and ws.blocksize() == 1: #this is just single bin data, it makes more sense to plot the bin plot_kwargs = {"axis": MantidAxType.BIN} plot([ws],errors=False, overplot=False, wksp_indices=[0], plot_kwargs=plot_kwargs) diff --git a/scripts/Muon/GUI/Common/load_run_widget/load_run_model.py b/scripts/Muon/GUI/Common/load_run_widget/load_run_model.py index 06d1eb6e72690bdb7f646c3e50ebcb22b80838ab..83bab80238e3103770c5c41989f756a5a66e6e90 100644 --- a/scripts/Muon/GUI/Common/load_run_widget/load_run_model.py +++ b/scripts/Muon/GUI/Common/load_run_widget/load_run_model.py @@ -33,13 +33,15 @@ class LoadRunWidgetModel(object): for filename in self._filenames: try: ws, run, filename, _ = load_utils.load_workspace_from_filename(filename) - except Exception as error: + except ValueError as error: failed_files += [(filename, error)] continue self._loaded_data_store.remove_data(run=[run]) - self._loaded_data_store.add_data(run=[run], workspace=ws, filename=filename, instrument=self._data_context.instrument) + self._loaded_data_store.add_data(run=[run], workspace=ws, filename=filename, + instrument=self._data_context.instrument) if failed_files: - message = load_utils.exception_message_for_failed_files(failed_files) + message = "The requested run could not be found. This could be due to: \n - The run does not yet exist." \ + "\n - The file was not found locally (please check the user directories)." raise ValueError(message) # This is needed to work with thread model diff --git a/scripts/Muon/GUI/Common/load_run_widget/load_run_presenter.py b/scripts/Muon/GUI/Common/load_run_widget/load_run_presenter.py index 3add628390b4051976d678edb432636a63305859..18ec38045b86658a131cca58afdde7977c331902 100644 --- a/scripts/Muon/GUI/Common/load_run_widget/load_run_presenter.py +++ b/scripts/Muon/GUI/Common/load_run_widget/load_run_presenter.py @@ -14,7 +14,6 @@ import Muon.GUI.Common.utilities.muon_file_utils as file_utils import Muon.GUI.Common.utilities.load_utils as load_utils from Muon.GUI.Common.utilities.run_string_utils import flatten_run_list from mantidqt.utils.observer_pattern import Observable -from mantid.api import FileFinder class LoadRunWidgetPresenter(object): @@ -158,10 +157,10 @@ class LoadRunWidgetPresenter(object): try: file_name = file_utils.file_path_for_instrument_and_run(self.get_current_instrument(), new_run) - FileFinder.findRuns(file_name) self.load_runs([file_name]) - except RuntimeError: - self._view.warning_popup("Requested run exceeds the current run for this instrument ") + except Exception: + # nothing is actually being caught here as it gets handled by thread_model.run + return def handle_decrement_run(self): decremented_run_list = self.get_decremented_run_list() diff --git a/scripts/test/Muon/load_run_widget/loadrun_presenter_current_run_test.py b/scripts/test/Muon/load_run_widget/loadrun_presenter_current_run_test.py index 58f63f092d9286caf8b3391564ed7247a2d7d500..1206f1c6d58f1dfda9b49e86baea7b86faebedd7 100644 --- a/scripts/test/Muon/load_run_widget/loadrun_presenter_current_run_test.py +++ b/scripts/test/Muon/load_run_widget/loadrun_presenter_current_run_test.py @@ -6,15 +6,26 @@ # SPDX - License - Identifier: GPL - 3.0 + import unittest from mantid.py3compat import mock +from mantid.py3compat.mock import patch from mantidqt.utils.qt.testing import start_qapplication -from qtpy.QtWidgets import QApplication, QWidget +from qtpy.QtWidgets import QApplication, QMessageBox, QWidget import Muon.GUI.Common.utilities.muon_file_utils as fileUtils +import Muon.GUI.Common.message_box as messageBox from Muon.GUI.Common.load_run_widget.load_run_model import LoadRunWidgetModel from Muon.GUI.Common.load_run_widget.load_run_presenter import LoadRunWidgetPresenter from Muon.GUI.Common.load_run_widget.load_run_view import LoadRunWidgetView +from Muon.GUI.Common.thread_model import ThreadModel, ThreadModelWorker from Muon.GUI.Common.test_helpers.context_setup import setup_context_for_tests +# this class is required to keep track of error signal emissions since the output is garbage collected by the time +# we reach the equal assertion +class MockSignalHandler(object): + def __init__(self, parent=None): + self.call_count = 0 + + def signalReceived(self): + self.call_count+=1 @start_qapplication class LoadRunWidgetLoadCurrentRunTest(unittest.TestCase): @@ -27,6 +38,7 @@ class LoadRunWidgetLoadCurrentRunTest(unittest.TestCase): return run_twice + @staticmethod def load_failure(self): raise ValueError("Error text") @@ -38,6 +50,13 @@ class LoadRunWidgetLoadCurrentRunTest(unittest.TestCase): def create_fake_workspace(self): return {'MainFieldDirection': 'transverse'} + def create_mock_signal_handler(self): + self.thread_model = ThreadModel(self.model) + self.thread_model_worker = ThreadModelWorker(self.thread_model) + self.thread_model_worker.signals.error = mock.Mock() + self.signal_handler = MockSignalHandler() + self.thread_model_worker.signals.error.connect(self.signal_handler.signalReceived()) + def setUp(self): # Store an empty widget to parent all the views, and ensure they are deleted correctly self.obj = QWidget() @@ -94,16 +113,19 @@ class LoadRunWidgetLoadCurrentRunTest(unittest.TestCase): self.assertEqual(self.view.get_run_edit_text(), '1234') - def test_load_current_run_displays_error_message_if_fails_to_load(self): + def test_load_current_run_emits_error_signal_if_fails_to_load(self): + self.create_mock_signal_handler() self.load_utils_patcher.load_workspace_from_filename = mock.Mock(side_effect=self.load_failure) self.presenter.handle_load_current_run() self.wait_for_thread(self.presenter._load_thread) - self.assertEqual(self.view.warning_popup.call_count, 1) + self.assertEqual(self.signal_handler.call_count, 1) @run_test_with_and_without_threading - def test_load_current_run_reverts_to_previous_data_if_fails_to_load(self): + # the following patch is required because the warning popup originates from thread_model in this case + @patch("Muon.GUI.Common.load_run_widget.load_run_presenter.thread_model.warning") + def test_load_current_run_reverts_to_previous_data_if_fails_to_load(self, warning_mock): # set up previous data workspace = self.create_fake_workspace() self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=(workspace, 1234, "1234.nxs", @@ -140,7 +162,11 @@ class LoadRunWidgetLoadCurrentRunTest(unittest.TestCase): self.assertEqual(self.presenter.workspaces, [workspace]) @run_test_with_and_without_threading - def test_load_current_run_displays_error_if_incrementing_past_current_run(self): + # the following patch is required because the warning popup also originates from thread_model in this case + @patch("Muon.GUI.Common.load_run_widget.load_run_presenter.thread_model.warning") + def test_load_current_run_emits_error_signal_if_incrementing_past_current_run(self, warning_mock): + self.create_mock_signal_handler() + # set up current run workspace = self.create_fake_workspace() self.load_utils_patcher.load_workspace_from_filename = mock.Mock(return_value=(workspace, 1234, "1234.nxs", @@ -152,7 +178,7 @@ class LoadRunWidgetLoadCurrentRunTest(unittest.TestCase): self.presenter.handle_increment_run() self.wait_for_thread(self.presenter._load_thread) - self.assertEqual(self.view.warning_popup.call_count, 1) + self.assertEqual(self.signal_handler.call_count, 1) if __name__ == '__main__': diff --git a/scripts/test/Muon/load_run_widget/loadrun_presenter_increment_decrement_test.py b/scripts/test/Muon/load_run_widget/loadrun_presenter_increment_decrement_test.py index 8f0536fc5ec50936d515cf91b854ed9bcecc4caf..0b94c43d56a2425b6492ef144eafc68a3b51a162 100644 --- a/scripts/test/Muon/load_run_widget/loadrun_presenter_increment_decrement_test.py +++ b/scripts/test/Muon/load_run_widget/loadrun_presenter_increment_decrement_test.py @@ -51,10 +51,6 @@ class LoadRunWidgetIncrementDecrementSingleFileModeTest(unittest.TestCase): self.load_utils_patcher = patcher.start() self.load_utils_patcher.exception_message_for_failed_files.return_value = '' - file_finder_patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_presenter.FileFinder') - self.addCleanup(file_finder_patcher.stop) - file_finder_patcher.start() - self.load_single_run() def tearDown(self): @@ -79,6 +75,7 @@ class LoadRunWidgetIncrementDecrementSingleFileModeTest(unittest.TestCase): def assert_view_has_not_changed(self): self.assertEqual(self.view.get_run_edit_text(), str(self._loaded_run)) + @staticmethod def load_failure(self): raise ValueError("Error text") diff --git a/scripts/test/Muon/load_run_widget/loadrun_presenter_multiple_file_test.py b/scripts/test/Muon/load_run_widget/loadrun_presenter_multiple_file_test.py index 307a8fe63fb26284ab9f5f6a7689d473ec3d838b..2635a6956804ea923b2bab2660861431ce6608b5 100644 --- a/scripts/test/Muon/load_run_widget/loadrun_presenter_multiple_file_test.py +++ b/scripts/test/Muon/load_run_widget/loadrun_presenter_multiple_file_test.py @@ -54,10 +54,6 @@ class LoadRunWidgetIncrementDecrementMultipleFileModeTest(unittest.TestCase): self.load_utils_patcher = patcher.start() self.load_utils_patcher.exception_message_for_failed_files.return_value = '' - file_finder_patcher = mock.patch('Muon.GUI.Common.load_run_widget.load_run_presenter.FileFinder') - self.addCleanup(file_finder_patcher.stop) - file_finder_patcher.start() - def tearDown(self): self.obj = None @@ -77,6 +73,7 @@ class LoadRunWidgetIncrementDecrementMultipleFileModeTest(unittest.TestCase): def assert_view_empty(self): self.assertEqual(self.view.get_run_edit_text(), "") + @staticmethod def load_failure(self): raise ValueError("Error text")