diff --git a/Testing/SystemTests/tests/analysis/ISISIndirectInelastic.py b/Testing/SystemTests/tests/analysis/ISISIndirectInelastic.py index 4920c2d6ec2e04a31b73161009c689b6ab3716ad..2a68c74d136de8814fe166837ca75ba69ad5a336 100644 --- a/Testing/SystemTests/tests/analysis/ISISIndirectInelastic.py +++ b/Testing/SystemTests/tests/analysis/ISISIndirectInelastic.py @@ -639,10 +639,12 @@ class ISISIndirectInelasticElwinAndMSDFit(with_metaclass(ABCMeta, ISISIndirectIn the other in this test. ''' - def _run(self): - '''Defines the workflow for the test''' + def __init__(self): + super(ISISIndirectInelasticElwinAndMSDFit, self).__init__() self.tolerance = 1e-7 + def _run(self): + '''Defines the workflow for the test''' elwin_input = '__ElWinMult_in' elwin_results = ['__ElWinMult_q', '__ElWinMult_q2', '__ElWinMult_elf'] @@ -699,6 +701,7 @@ class OSIRISElwinAndMSDFit(ISISIndirectInelasticElwinAndMSDFit): def __init__(self): ISISIndirectInelasticElwinAndMSDFit.__init__(self) + self.tolerance = 5e-6 self.files = ['osi97935_graphite002_red.nxs', 'osi97936_graphite002_red.nxs'] self.eRange = [-0.02, 0.02] diff --git a/qt/python/mantidqtpython/mantidqt.sip b/qt/python/mantidqtpython/mantidqt.sip index d119fdd50bec219a4911db181c85c08490a2a661..a59641437a6935e4185d194e306bf5152b7e6c57 100644 --- a/qt/python/mantidqtpython/mantidqt.sip +++ b/qt/python/mantidqtpython/mantidqt.sip @@ -1565,6 +1565,7 @@ void setCell(const QString &, int, int, int parentRow = 0, int parentColumn = 0) QString getCell(int, int, int parentRow = 0, int parentColumn = 0); int getNumberOfRows(); void clearTable(); +void skipProcessing(); signals: void runPythonCode(const QString &); diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/DataProcessorPresenter.h b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/DataProcessorPresenter.h index d717911d43af081b9543ff5cc013789837d967d2..166b8646c6203d3c3ccdd942b1ae4789b446528b 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/DataProcessorPresenter.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/DataProcessorPresenter.h @@ -105,6 +105,8 @@ public: int parentColumn) = 0; virtual int getNumberOfRows() = 0; virtual void clearTable() = 0; + + virtual void skipProcessing() = 0; }; } } diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/DataProcessorView.h b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/DataProcessorView.h index 0e3287344cc2f5c4b47eaf016fbe2fe3b8243cb0..e03b968df62626020157ec0c1f23744002cab048 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/DataProcessorView.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/DataProcessorView.h @@ -113,6 +113,10 @@ public: // Methods to emit signals virtual void emitProcessClicked() = 0; virtual void emitProcessingFinished() = 0; + + // + virtual void skipProcessing() = 0; + }; } } diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/GenericDataProcessorPresenter.h b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/GenericDataProcessorPresenter.h index db8165d9a7b5d44f003302fc121d4f8670272064..dcdb6aa046c5e4c3299d972626282805f18c7366 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/GenericDataProcessorPresenter.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/GenericDataProcessorPresenter.h @@ -143,6 +143,8 @@ public: bool isProcessing() const override; void setForcedReProcessing(bool forceReProcessing) override; + void skipProcessing() override; + protected: template <typename T> using QOrderedSet = QMap<T, std::nullptr_t>; // The table view we're managing @@ -303,6 +305,7 @@ private: bool isProcessed(int position) const; bool isProcessed(int position, int parent) const; bool m_forceProcessing = false; + bool m_skipProcessing = false; // List of workspaces the user can open QSet<QString> m_workspaceList; diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/MockObjects.h b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/MockObjects.h index 8ec04aa9962b179538ccd1d4ddcb922a0a8bef1a..e8533458ed13beeed9ca625d783d0788ba5ba48d 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/MockObjects.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/MockObjects.h @@ -67,6 +67,7 @@ public: // Processing options MOCK_METHOD1(setForcedReProcessing, void(bool)); + MOCK_METHOD0(skipProcessing, void()); // Accessor MOCK_CONST_METHOD0(getCurrentInstrument, QString()); @@ -144,6 +145,7 @@ public: MOCK_CONST_METHOD2(giveUserWarning, void(const QString &prompt, const QString &title)); MOCK_METHOD0(publishCommandsMocked, void()); + MOCK_METHOD0(skipProcessing, void()); MOCK_METHOD1(setForcedReProcessing, void(bool)); private: diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/QDataProcessorWidget.h b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/QDataProcessorWidget.h index 31dc33a7f564136a0e501da49d429ba9c50a7ceb..71cdbfacc99e9be5ec242f5a3c375fdf75843a30 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/QDataProcessorWidget.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/DataProcessorUI/QDataProcessorWidget.h @@ -157,6 +157,8 @@ public: void emitProcessingFinished() override { emit processingFinished(); } + void skipProcessing() override; + signals: void processButtonClicked(); void processingFinished(); diff --git a/qt/widgets/common/src/DataProcessorUI/GenericDataProcessorPresenter.cpp b/qt/widgets/common/src/DataProcessorUI/GenericDataProcessorPresenter.cpp index 1becdaabc7a919bc81c2953b9381b03e6fc00281..fd836a0b2a50beee34e65c15c49de9bd1a1e4c60 100644 --- a/qt/widgets/common/src/DataProcessorUI/GenericDataProcessorPresenter.cpp +++ b/qt/widgets/common/src/DataProcessorUI/GenericDataProcessorPresenter.cpp @@ -300,7 +300,7 @@ Process selected data void GenericDataProcessorPresenter::process() { // Emit a signal hat the process is starting m_view->emitProcessClicked(); - + if (GenericDataProcessorPresenter::m_skipProcessing) { m_skipProcessing = false; return; } m_selectedData = m_manager->selectedData(m_promptUser); // Don't continue if there are no items selected @@ -1811,6 +1811,13 @@ int GenericDataProcessorPresenter::getNumberOfRows() { **/ void GenericDataProcessorPresenter::clearTable() { m_manager->deleteRow(); } +/** + * Flag used to stop processing +**/ +void GenericDataProcessorPresenter::skipProcessing() { + m_skipProcessing = true; +} + } } } diff --git a/qt/widgets/common/src/DataProcessorUI/QDataProcessorWidget.cpp b/qt/widgets/common/src/DataProcessorUI/QDataProcessorWidget.cpp index 43a21513fa493dbd5bcab6fe12318490dcd28483..f7c4d7ff0e45205bd65a3212bc610c996b5303b1 100644 --- a/qt/widgets/common/src/DataProcessorUI/QDataProcessorWidget.cpp +++ b/qt/widgets/common/src/DataProcessorUI/QDataProcessorWidget.cpp @@ -686,6 +686,9 @@ QString QDataProcessorWidget::getCurrentInstrument() const { return ui.comboProcessInstrument->currentText(); } +void QDataProcessorWidget::skipProcessing() { + m_presenter->skipProcessing(); +} } // namespace DataProcessor } // namespace MantidWidgets } // namespace Mantid diff --git a/qt/widgets/common/test/DataProcessorUI/GenericDataProcessorPresenterTest.h b/qt/widgets/common/test/DataProcessorUI/GenericDataProcessorPresenterTest.h index b9825612efcfa1f34c72e764052c6c9606b284f4..016c4540c5ead6cd18a651b8f5771b6ce9bc1885 100644 --- a/qt/widgets/common/test/DataProcessorUI/GenericDataProcessorPresenterTest.h +++ b/qt/widgets/common/test/DataProcessorUI/GenericDataProcessorPresenterTest.h @@ -1129,6 +1129,70 @@ public: TS_ASSERT(Mock::VerifyAndClearExpectations(&mockMainPresenter)); } + void testProcessExitsIfSkipProcessingIsTrue() { + NiceMock<MockDataProcessorView> mockDataProcessorView; + NiceMock<MockProgressableView> mockProgress; + NiceMock<MockMainPresenter> mockMainPresenter; + GenericDataProcessorPresenterNoThread presenter( + createReflectometryWhiteList(), createReflectometryPreprocessMap(), + createReflectometryProcessor(), createReflectometryPostprocessor()); + presenter.acceptViews(&mockDataProcessorView, &mockProgress); + presenter.accept(&mockMainPresenter); + + presenter.skipProcessing(); + + createPrefilledWorkspace("TestWorkspace", presenter.getWhiteList()); + EXPECT_CALL(mockDataProcessorView, getWorkspaceToOpen()) + .Times(1) + .WillRepeatedly(Return("TestWorkspace")); + presenter.notify(DataProcessorPresenter::OpenTableFlag); + + std::set<int> grouplist; + grouplist.insert(0); + + createTOFWorkspace("TOF_12345", "12345"); + createTOFWorkspace("TOF_12346", "12346"); + + // We should not receive any errors + EXPECT_CALL(mockDataProcessorView, giveUserCritical(_, _)).Times(0); + + // The user hits the "process" button with the first group selected + EXPECT_CALL(mockDataProcessorView, getSelectedChildren()) + .Times(0); + EXPECT_CALL(mockDataProcessorView, getSelectedParents()) + .Times(0); + EXPECT_CALL(mockMainPresenter, getPreprocessingOptionsAsString()) + .Times(0); + EXPECT_CALL(mockMainPresenter, getPreprocessingProperties()) + .Times(0); + EXPECT_CALL(mockMainPresenter, getProcessingOptions()) + .Times(0); + EXPECT_CALL(mockMainPresenter, getPostprocessingOptions()) + .Times(0); + EXPECT_CALL(mockDataProcessorView, resume()).Times(0); + EXPECT_CALL(mockMainPresenter, resume()).Times(0); + EXPECT_CALL(mockDataProcessorView, getEnableNotebook()) + .Times(0); + EXPECT_CALL(mockDataProcessorView, requestNotebookPath()).Times(0); + + presenter.notify(DataProcessorPresenter::ProcessFlag); + + // Tidy up + AnalysisDataService::Instance().remove("TestWorkspace"); + AnalysisDataService::Instance().remove("IvsQ_binned_TOF_12345"); + AnalysisDataService::Instance().remove("IvsQ_TOF_12345"); + AnalysisDataService::Instance().remove("IvsLam_TOF_12345"); + AnalysisDataService::Instance().remove("TOF_12345"); + AnalysisDataService::Instance().remove("IvsQ_binned_TOF_12346"); + AnalysisDataService::Instance().remove("IvsQ_TOF_12346"); + AnalysisDataService::Instance().remove("IvsLam_TOF_12346"); + AnalysisDataService::Instance().remove("TOF_12346"); + AnalysisDataService::Instance().remove("IvsQ_TOF_12345_TOF_12346"); + + TS_ASSERT(Mock::VerifyAndClearExpectations(&mockDataProcessorView)); + TS_ASSERT(Mock::VerifyAndClearExpectations(&mockMainPresenter)); + } + void testTreeUpdatedAfterProcess() { NiceMock<MockDataProcessorView> mockDataProcessorView; NiceMock<MockProgressableView> mockProgress; diff --git a/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py b/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py index 9ec1ebf48b7f783d3e3868d8668621a8bc09bcea..2101bbb7dd61fc2380e6ff432b34867a5818420c 100644 --- a/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py +++ b/scripts/Interface/ui/sans_isis/sans_data_processor_gui.py @@ -505,6 +505,9 @@ class SANSDataProcessorGui(QtGui.QMainWindow, ui_sans_data_processor_window.Ui_S else: gui_element.addItem(element) + def halt_process_flag(self): + self.data_processor_table.skipProcessing() + @staticmethod def _set_enum_as_element_in_combo_box(gui_element, element, expected_type): value_as_string = expected_type.to_string(element) diff --git a/scripts/SANS/sans/gui_logic/presenter/run_tab_presenter.py b/scripts/SANS/sans/gui_logic/presenter/run_tab_presenter.py index fac1e55514a595baf008f231fe2f5eb944c1ebc0..c3e8e455283ce7f3fc4ee1deea50facc9797fa40 100644 --- a/scripts/SANS/sans/gui_logic/presenter/run_tab_presenter.py +++ b/scripts/SANS/sans/gui_logic/presenter/run_tab_presenter.py @@ -241,6 +241,7 @@ class RunTabPresenter(object): # 1. Set up the states and convert them into property managers states = self.get_states() if not states: + self._view.halt_process_flag() raise RuntimeError("There seems to have been an issue with setting the states. Make sure that a user file" "has been loaded") property_manager_service = PropertyManagerService() @@ -342,6 +343,7 @@ class RunTabPresenter(object): if not self.is_empty_row(row): sample_scatter = self._view.get_cell(row, 0) if not sample_scatter: + self._view.halt_process_flag() raise RuntimeError("Row {} has not SampleScatter specified. Please correct this.".format(row)) def get_processing_options(self): @@ -841,6 +843,7 @@ class RunTabPresenter(object): self.sans_logger.error("There was a bad entry for row {}. Ensure that the path to your files has " "been added to the Mantid search directories! See here for more " "details: {}".format(row, str(e))) + self._view.halt_process_flag() raise RuntimeError("There was a bad entry for row {}. Ensure that the path to your files has " "been added to the Mantid search directories! See here for more " "details: {}".format(row, str(e))) diff --git a/scripts/SANS/sans/test_helper/mock_objects.py b/scripts/SANS/sans/test_helper/mock_objects.py index b6a6bd98a1e54b09d4f4b631bfac1ea4e982a15f..c0f441bfd3eb13ff02919ffdd63424b191f6b6e0 100644 --- a/scripts/SANS/sans/test_helper/mock_objects.py +++ b/scripts/SANS/sans/test_helper/mock_objects.py @@ -79,6 +79,7 @@ def create_mock_view(user_file_path, batch_file_path=None): masking_table = create_mock_masking_table() view.masking_table = masking_table + view.halt_process_flag = mock.MagicMock() # --------------------- # Mocking properties # --------------------- diff --git a/scripts/test/SANS/gui_logic/run_tab_presenter_test.py b/scripts/test/SANS/gui_logic/run_tab_presenter_test.py index b8ebf1102875a25e283b17fee46e2d709969a0a9..db3c7871cb0df517c2d20195a7a21922ac2a7f69 100644 --- a/scripts/test/SANS/gui_logic/run_tab_presenter_test.py +++ b/scripts/test/SANS/gui_logic/run_tab_presenter_test.py @@ -4,12 +4,11 @@ from __future__ import (absolute_import, division, print_function) import unittest import sys -import mantid from mantid.kernel import config from mantid.kernel import PropertyManagerDataService from sans.gui_logic.presenter.run_tab_presenter import RunTabPresenter -from sans.common.enums import (SANSFacility, ReductionDimensionality, SaveType, OutputMode, ISISReductionMode, +from sans.common.enums import (SANSFacility, ReductionDimensionality, SaveType, ISISReductionMode, RangeStepType, FitType) from sans.test_helper.user_file_test_helper import (create_user_file, sample_user_file) from sans.test_helper.mock_objects import (create_mock_view) @@ -270,6 +269,67 @@ class RunTabPresenterTest(unittest.TestCase): self._clear_property_manager_data_service() + def test_that_calls_halt_process_flag_if_user_file_has_not_been_loaded_and_process_is_run(self): + # Arrange + self._clear_property_manager_data_service() + batch_file_path, user_file_path, presenter, view = self._get_files_and_mock_presenter(BATCH_FILE_TEST_CONTENT_2) + + with self.assertRaises(RuntimeError): + presenter.on_processed_clicked() + + # Assert + # We should have raised an exception and called halt process flag + self.assertTrue(view.halt_process_flag.call_count == 1) + # clean up + self._remove_files(user_file_path=user_file_path, batch_file_path=batch_file_path) + + self._clear_property_manager_data_service() + + def test_that_calls_halt_process_flag_if_state_are_invalid_and_process_is_run(self): + # Arrange + self._clear_property_manager_data_service() + batch_file_path, user_file_path, presenter, view = self._get_files_and_mock_presenter(BATCH_FILE_TEST_CONTENT_2) + + presenter.on_batch_file_load() + presenter.on_user_file_load() + + #Set invalid state + presenter._state_model.event_slices = 'Hello' + + with self.assertRaises(RuntimeError): + presenter.on_processed_clicked() + + # Assert + # We should have raised an exception and called halt process flag + self.assertTrue(view.halt_process_flag.call_count == 1) + #self.assertTrue(has_raised) + # clean up + self._remove_files(user_file_path=user_file_path, batch_file_path=batch_file_path) + + self._clear_property_manager_data_service() + + def test_that_calls_halt_process_flag_if_states_are_not_retrievable_and_process_is_run(self): + # Arrange + self._clear_property_manager_data_service() + batch_file_path, user_file_path, presenter, view = self._get_files_and_mock_presenter(BATCH_FILE_TEST_CONTENT_2) + + presenter.on_batch_file_load() + presenter.on_user_file_load() + + presenter.get_states = mock.MagicMock(return_value='') + + with self.assertRaises(RuntimeError): + presenter.on_processed_clicked() + + # Assert + # We should have raised an exception and called halt process flag + self.assertTrue(view.halt_process_flag.call_count == 1) + #self.assertTrue(has_raised) + # clean up + self._remove_files(user_file_path=user_file_path, batch_file_path=batch_file_path) + + self._clear_property_manager_data_service() + def test_that_can_add_new_masks(self): # Arrange self._clear_property_manager_data_service()