diff --git a/docs/source/release/v5.0.0/muon.rst b/docs/source/release/v5.0.0/muon.rst index 60959a680b584933e941e2c56911a531cf73460f..337a960f43d61b5e00137a135debdfe6dae40e5d 100644 --- a/docs/source/release/v5.0.0/muon.rst +++ b/docs/source/release/v5.0.0/muon.rst @@ -34,6 +34,8 @@ Muon Analysis 2 and Frequency Domain Interfaces - Fixed a bug that prevented PSI data from being loaded. - Reworked the fitting tab to improve the user experience when doing single, and simultaneous fits. - Addition of a sequential fitting tab, enabling both sequential, and simultaneous sequential fits. +- Fixed a bug where Elemental analysis gave an error when loading data. +- Elemental analysis bug has been fixed that prevented co-adding data. Bug Fixes ######### diff --git a/scripts/MultiPlotting/subplot/subplot.py b/scripts/MultiPlotting/subplot/subplot.py index 2322cb96de85a2d83972e6125334c1db1a042725..8b6aed55b1eff50b9b2110a22bc9769598ea17b8 100644 --- a/scripts/MultiPlotting/subplot/subplot.py +++ b/scripts/MultiPlotting/subplot/subplot.py @@ -253,7 +253,7 @@ class subplot(QtWidgets.QWidget): self.signal_rm_subplot.emit(subplot_name) def _rm_ws_from_plots(self, workspace_name): - keys = deepcopy(self._context.subplots.keys()) + keys = deepcopy(list(self._context.subplots.keys())) for subplot in keys: labels = self._context.get_lines_from_WS(subplot, workspace_name) for label in labels: diff --git a/scripts/Muon/GUI/Common/load_widget/load_presenter.py b/scripts/Muon/GUI/Common/load_widget/load_presenter.py index a67c5f4931c3ccb38cd87e4dbc6f0602fdd9b73a..8f0d8820ceb6fe8bcd49862830d2f702bb645576 100644 --- a/scripts/Muon/GUI/Common/load_widget/load_presenter.py +++ b/scripts/Muon/GUI/Common/load_widget/load_presenter.py @@ -7,6 +7,7 @@ from __future__ import absolute_import, print_function from Muon.GUI.Common import thread_model +import mantid.simpleapi as mantid class LoadPresenter(object): @@ -16,29 +17,27 @@ class LoadPresenter(object): self.co_model = co_model self.load_thread = None self.co_thread = None + self._current_run = None - self.view.on_load_clicked(self.equalise_loaded_runs) - self.view.on_load_clicked(self.equalise_last_loaded_run) self.view.on_load_clicked(self.load_run) self.view.on_load_clicked(self.co_model.wipe_co_runs) - self.view.on_co_add_clicked(self.equalise_loaded_runs) - self.view.on_co_add_clicked(self.equalise_last_loaded_run) self.view.on_co_add_clicked(self.co_add_run) self.view.on_spinbox_changed(self.update_models) - def equalise_loaded_runs(self): - loaded_runs = max( - self.co_model.loaded_runs, - self.load_model.loaded_runs) - self.co_model.loaded_runs = loaded_runs - self.load_model.loaded_runs = loaded_runs + def equalise_last_loaded_run(self, runs): + if self.co_model.loaded_runs == {} and self.load_model.loaded_runs == {}: + return + try: + self._current_run = str(list(runs)[-1]) + except IndexError: + self.view.warning("The run was not found.") + return - def equalise_last_loaded_run(self): - last_run = max( - self.co_model.last_loaded_runs, - self.load_model.last_loaded_runs) - self.co_model.last_loaded_runs = last_run - self.load_model.last_loaded_runs = last_run + def set_coadd_loaded_run(self): + self.equalise_last_loaded_run(self.co_model.loaded_runs.keys()) + + def set_loaded_run(self): + self.equalise_last_loaded_run(self.load_model.loaded_runs.keys()) def update_models(self, run): self.load_model.set_run(run) @@ -63,11 +62,13 @@ class LoadPresenter(object): self.view.enable_buttons() def end_load_thread(self): + self.set_loaded_run() self.enable_buttons() self.load_thread.deleteLater() self.load_thread = None def end_co_thread(self): + self.set_coadd_loaded_run() self.enable_buttons() self.co_thread.deleteLater() self.co_thread = None @@ -77,7 +78,7 @@ class LoadPresenter(object): def last_loaded_run(self): try: - return self.load_model.last_loaded_runs[-1] + return self._current_run except IndexError: return None @@ -88,4 +89,10 @@ class LoadPresenter(object): self.view.unreg_on_loading_finished(slot) def get_run_num_loaded_detectors(self, run): - return self.load_model.num_loaded_detectors[run] + num_detectors = 0 + try: + group = mantid.mtd[run] + num_detectors = len(group) + except KeyError: + num_detectors = 0 + return num_detectors diff --git a/scripts/Muon/GUI/Common/load_widget/load_view.py b/scripts/Muon/GUI/Common/load_widget/load_view.py index 27bd505ca566ad54c4a92f1e7ec71817694bc436..fb86a3e6994b46cb16cd88569a132ae49737ec25 100644 --- a/scripts/Muon/GUI/Common/load_widget/load_view.py +++ b/scripts/Muon/GUI/Common/load_widget/load_view.py @@ -9,6 +9,7 @@ from __future__ import absolute_import from qtpy import QtWidgets, QtCore from mantidqt.widgets import manageuserdirectories +from Muon.GUI.Common import message_box class LoadView(QtWidgets.QWidget): @@ -84,3 +85,6 @@ class LoadView(QtWidgets.QWidget): self.sig_loading_finished.disconnect(slot) except TypeError: return + + def warning(self,msg): + message_box.warning(msg) diff --git a/scripts/Muon/GUI/ElementalAnalysis/LoadWidget/load_model.py b/scripts/Muon/GUI/ElementalAnalysis/LoadWidget/load_model.py index ca755d07126e900f5ca31738423d911e8926ca01..511494f2b913e2640c4bd9dc6941cf691180cd61 100644 --- a/scripts/Muon/GUI/ElementalAnalysis/LoadWidget/load_model.py +++ b/scripts/Muon/GUI/ElementalAnalysis/LoadWidget/load_model.py @@ -49,15 +49,20 @@ class CoLoadModel(lutils.LModel): def add_runs(self, run1, run2, suffix): # prevent new suffix being appended to old one - out = lutils.replace_workspace_name_suffix(run1, suffix) + out = suffix+";" + run1.split(";")[1] mantid.Plus(run1, run2, OutputWorkspace=out) return out def co_load_run(self, workspace): run = lutils.hyphenise(self.co_runs) - self.last_loaded_runs.append(run) to_add = [ self.add_runs(run1, run2, run) for run1, run2 in zip(*lutils.flatten_run_data(self.workspace, workspace)) ] - self.workspace = lutils.group_by_detector(run, to_add) + self.loaded_runs[run] = to_add + self.add_co_load_to_group(to_add,run) + + def add_co_load_to_group(self, to_add,run): + overall_ws = mantid.GroupWorkspaces(to_add[0], OutputWorkspace=str(run)) + for index in range(1, len(to_add)): + overall_ws.add(to_add[index]) diff --git a/scripts/Muon/GUI/ElementalAnalysis/LoadWidget/load_utils.py b/scripts/Muon/GUI/ElementalAnalysis/LoadWidget/load_utils.py index a835d8e79f896b24400fb5a08c81b86632f1a398..3665b297e502a05fafba1f738bf786ce3606597a 100644 --- a/scripts/Muon/GUI/ElementalAnalysis/LoadWidget/load_utils.py +++ b/scripts/Muon/GUI/ElementalAnalysis/LoadWidget/load_utils.py @@ -5,6 +5,7 @@ # & Institut Laue - Langevin # SPDX - License - Identifier: GPL - 3.0 + from __future__ import (absolute_import, division, unicode_literals) +from collections import OrderedDict import glob import os @@ -21,8 +22,8 @@ num_files_per_detector = 3 class LModel(object): def __init__(self): self.run = 0 - self.num_loaded_detectors ={} - self.loaded_runs = {} + self.num_loaded_detectors =OrderedDict() + self.loaded_runs = OrderedDict() self.last_loaded_runs = [] def _load(self, inputs): @@ -50,7 +51,7 @@ class LModel(object): loaded_detectors[ws_name[0]] = 1 num_loaded_detectors = len(loaded_detectors) self._load(workspaces) - self.loaded_runs[self.run] = merge_workspaces(self.run, workspaces.values()) + self.loaded_runs.update({self.run: merge_workspaces(self.run, workspaces.values())}) self.num_loaded_detectors[self.run] = num_loaded_detectors self.last_loaded_runs.append(self.run) return self.loaded_runs[self.run] @@ -214,9 +215,8 @@ def replace_workspace_name_suffix(name, suffix): def flatten_run_data(*workspaces): out = [] - for workspace in workspaces: - detectors = [mantid.mtd[detector] for detector in workspace] - out.append(sorted([_workspace.getName() for detector in detectors for _workspace in detector])) + for workspace_list in workspaces: + out.append(sorted([ws_name for ws_name in workspace_list])) return out diff --git a/scripts/Muon/GUI/ElementalAnalysis/elemental_analysis.py b/scripts/Muon/GUI/ElementalAnalysis/elemental_analysis.py index efbaab2444bd32f7bbcd1fb521f0844d15712106..f02a7882031531e996be1edb762b1560a98e10a6 100644 --- a/scripts/Muon/GUI/ElementalAnalysis/elemental_analysis.py +++ b/scripts/Muon/GUI/ElementalAnalysis/elemental_analysis.py @@ -289,8 +289,9 @@ class ElementalAnalysisGui(QtWidgets.QMainWindow): if last_run is None: return # check all detectors are loaded + num_detectors = self.load_widget.get_run_num_loaded_detectors(last_run) for j, detector in enumerate(self.detectors.getNames()): - if j < self.load_widget.get_run_num_loaded_detectors(last_run): + if j < num_detectors: self.detectors.enableDetector(detector) else: # disable checkbox and uncheck box diff --git a/scripts/test/Muon/LoadWidgetPresenter_test.py b/scripts/test/Muon/LoadWidgetPresenter_test.py index ae70faebfbc83c34e8a1d78bdf74b550ee031e13..0d928b7091def62404d2706e587ea069f67b3183 100644 --- a/scripts/test/Muon/LoadWidgetPresenter_test.py +++ b/scripts/test/Muon/LoadWidgetPresenter_test.py @@ -12,7 +12,7 @@ from mantidqt.utils.qt.testing import start_qapplication from Muon.GUI.Common.load_widget.load_presenter import LoadPresenter from Muon.GUI.Common.load_widget.load_view import LoadView from Muon.GUI.ElementalAnalysis.LoadWidget.load_model import LoadModel, CoLoadModel - +from collections import OrderedDict @start_qapplication class LoadPresenterTest(unittest.TestCase): @@ -24,11 +24,24 @@ class LoadPresenterTest(unittest.TestCase): self._view, self._load_model, self._co_model) self.view = self.presenter.view - def test_equalise_loaded_runs(self): - self.presenter.co_model.loaded_runs = 5 - self.presenter.load_model.loaded_runs = 10 - self.presenter.equalise_loaded_runs() - self.assertEqual(self.presenter.co_model.loaded_runs, 10) + def test_equalise_last_loaded_run_empty(self): + runs = OrderedDict() + self.presenter.co_model.loaded_runs = runs + self.presenter.load_model.loaded_runs = runs + self.presenter.equalise_last_loaded_run(runs) + self.assertEqual(self.presenter._current_run, None) + + def test_equalise_last_loaded_run_data(self): + # need to add each in tern for Python 2 + runs = OrderedDict() + runs[1]=[] + runs[2] =[] + runs[5] =[] + runs[3]=[] + self.presenter.co_model.loaded_runs = runs + self.presenter.load_model.loaded_runs = runs + self.presenter.equalise_last_loaded_run(runs) + self.assertEqual(self.presenter._current_run, '3') def test_update_models(self): self.presenter.load_model = LoadModel() @@ -46,6 +59,47 @@ class LoadPresenterTest(unittest.TestCase): self.presenter.disable_buttons() self.assertEqual(self.view.disable_buttons.call_count, 1) + def test_set_coadd_loaded_run(self): + self.presenter.equalise_last_loaded_run = mock.Mock() + runs = OrderedDict() + self.presenter.co_model.loaded_runs = runs + self.presenter.load_model.loaded_runs = OrderedDict() + self.presenter.set_coadd_loaded_run() + self.presenter.equalise_last_loaded_run.assert_called_with(runs.keys()) + + def test_set_loaded_run(self): + self.presenter.equalise_last_loaded_run = mock.Mock() + runs = OrderedDict() + self.presenter.co_model.loaded_runs = OrderedDict() + self.presenter.load_model.loaded_runs = runs + self.presenter.set_loaded_run() + self.presenter.equalise_last_loaded_run.assert_called_with(runs.keys()) + + def test_end_load_thread(self): + self.presenter.set_loaded_run = mock.Mock() + self.presenter.enable_buttons = mock.Mock() + self.presenter.load_thread = mock.Mock() + self.presenter.load_thread.deleteLater = mock.Mock() + + self.presenter.end_load_thread() + self.assertEqual(self.presenter.set_loaded_run.call_count, 1) + self.assertEqual(self.presenter.enable_buttons.call_count, 1) + self.assertEqual(self.presenter.load_thread, None) + + def test_end_co_thread(self): + self.presenter.set_coadd_loaded_run = mock.Mock() + self.presenter.enable_buttons = mock.Mock() + self.presenter.co_thread = mock.Mock() + self.presenter.co_thread.deleteLater = mock.Mock() + + self.presenter.end_co_thread() + self.assertEqual(self.presenter.set_coadd_loaded_run.call_count, 1) + self.assertEqual(self.presenter.enable_buttons.call_count, 1) + self.assertEqual(self.presenter.co_thread, None) + + def test_last_loaded_run(self): + self.presenter._current_run = 5 + self.assertEquals(self.presenter.last_loaded_run(), 5) if __name__ == "__main__": unittest.main() diff --git a/scripts/test/Muon/elemental_analysis/load_model_test.py b/scripts/test/Muon/elemental_analysis/load_model_test.py index a7e4272e2d768479dc55a47c2daad03166fa24aa..a9fcb50f8bad34f0a2d51f71daccf0f4d056f2ef 100644 --- a/scripts/test/Muon/elemental_analysis/load_model_test.py +++ b/scripts/test/Muon/elemental_analysis/load_model_test.py @@ -9,6 +9,7 @@ from __future__ import print_function import unittest from mantid.py3compat import mock +import mantid.simpleapi as mantid from Muon.GUI.ElementalAnalysis.LoadWidget import load_model @@ -100,25 +101,33 @@ class CoLoadModel(unittest.TestCase): @mock.patch('Muon.GUI.ElementalAnalysis.LoadWidget.load_model.lutils.replace_workspace_name_suffix') @mock.patch('Muon.GUI.ElementalAnalysis.LoadWidget.load_model.mantid') def test_that_add_runs_renames_output_ws_and_adds_correctly(self, mock_mantid, mock_replace_ws): - left_ws = 'left_ws_1' - right_ws = 'right-ws' - suffix = 'my-suffix' + left_ws = '2695; detector 1' + right_ws = '2696; detector 1' + suffix = '2695-2696' mock_replace_ws.return_value = 'left_ws_my-suffix' added_runs = self.model.add_runs(left_ws, right_ws, suffix) - mock_replace_ws.assert_called_with(left_ws, suffix) - mock_mantid.Plus.assert_called_with(left_ws, right_ws, OutputWorkspace='left_ws_my-suffix') - self.assertEqual(added_runs, 'left_ws_my-suffix') + mock_mantid.Plus.assert_called_with(left_ws, right_ws, OutputWorkspace='2695-2696; detector 1') + self.assertEqual(added_runs, '2695-2696; detector 1') @mock.patch('Muon.GUI.ElementalAnalysis.LoadWidget.load_model.lutils') def test_that_co_load_run_calls_right_functions(self, mock_lutils): mock_ws = mock.Mock() - mock_lutils.hyphenise.return_value = 1234 - self.model.co_load_run(mock_ws) + self.model.workspace = mock.Mock() + mock_lutils.hyphenise.return_value = "2695-2696" + workspace1 = ["2695; detector 1", "2695; detector 2"] + workspace2 = ["2696; detector 1", "2696; detector 2"] + for ws in workspace1: + mantid.CreateSampleWorkspace(OutputWorkspace = ws) + for ws in workspace2: + mantid.CreateSampleWorkspace(OutputWorkspace = ws) + mock_lutils.flatten_run_data = mock.Mock(return_value=[workspace1,workspace2]) + self.model.add_co_load_to_group = mock.Mock() + self.model.co_load_run(mock_ws) + self.assertEquals(self.model.add_co_load_to_group.call_count,1) self.assertEqual(mock_lutils.hyphenise.call_count, 1) - self.assertTrue(1234 in self.model.last_loaded_runs) - self.assertEqual(mock_lutils.group_by_detector.call_count, 1) + self.assertTrue("2695-2696" in self.model.loaded_runs.keys()) if __name__ == '__main__': diff --git a/scripts/test/Muon/elemental_analysis/load_utils_test.py b/scripts/test/Muon/elemental_analysis/load_utils_test.py index d32338062987d9c20ae4f0eb2e43bc41fcfc40f8..7355e530697c8190ad57605f11702072ee29949c 100644 --- a/scripts/test/Muon/elemental_analysis/load_utils_test.py +++ b/scripts/test/Muon/elemental_analysis/load_utils_test.py @@ -152,14 +152,9 @@ class LoadUtilsTest(unittest.TestCase): def test_flatten_run_data(self): - test_workspaces = [mantid.CreateSampleWorkspace(OutputWorkspace=name) for name in self.test_ws_names] - workspaces = [] - for i in range(0, len(test_workspaces), 2): - name = str(i) - mantid.GroupWorkspaces(test_workspaces[i:i + 2], OutputWorkspace=name) - workspaces.append(name) - - self.assertEquals(lutils.flatten_run_data(workspaces), [self.test_ws_names]) + test_1 = ["1_det_1", "1_det_2"] + test_2 = ["2_det_1", "2_det_2"] + self.assertEquals(lutils.flatten_run_data(test_1,test_2), [test_1,test_2]) def test_replace_workspace_name_suffix(self): tests = {self.test_ws_name: "suffix", "_".join([self.test_ws_name, "test"]): "suffix"}