Skip to content
Snippets Groups Projects
Unverified Commit c7abedc2 authored by Dan Nixon's avatar Dan Nixon Committed by GitHub
Browse files

Merge pull request #27431 from StephenSmith25/27430_Elemental_analysis_not_support_legacy_data

Fix issue with Elemental analysis not supporting legacy data
parents e292c29f 123d3272
No related branches found
No related tags found
No related merge requests found
......@@ -9,5 +9,9 @@ MuSR Changes
putting new features at the top of the section, followed by
improvements, followed by bug fixes.
Improvements
############
- The elemental analysis GUI can now handle legacy data which is missing a response dataset, e.g Delayed.
:ref:`Release 4.3.0 <v4.3.0>`
\ No newline at end of file
......@@ -86,3 +86,6 @@ class LoadPresenter(object):
def unreg_on_loading_finished(self, slot):
self.view.unreg_on_loading_finished(slot)
def get_run_num_loaded_detectors(self, run):
return self.load_model.num_loaded_detectors[run]
......@@ -17,5 +17,11 @@ class DetectorsPresenter(object):
def setStateQuietly(self, name, state):
self.view.setStateQuietly(name, state)
def enableDetector(self, name):
self.view.enableDetector(name)
def disableDetector(self, name):
self.view.disableDetector(name)
def getNames(self):
return self.view.widgets.keys()
......@@ -33,3 +33,9 @@ class DetectorsView(QtWidgets.QWidget):
self.widgets[name].blockSignals(True)
self.widgets[name].setChecked(state)
self.widgets[name].blockSignals(False)
def enableDetector(self, name):
self.widgets[name].setEnabled(True)
def disableDetector(self, name):
self.widgets[name].setEnabled(False)
......@@ -15,11 +15,13 @@ import mantid.simpleapi as mantid
type_keys = {"10": "Prompt", "20": "Delayed", "99": "Total"}
spectrum_index = {"Delayed": 1, "Prompt": 2, "Total": 3}
num_files_per_detector = 3
class LModel(object):
def __init__(self):
self.run = 0
self.num_loaded_detectors ={}
self.loaded_runs = {}
self.last_loaded_runs = []
......@@ -42,8 +44,14 @@ class LModel(object):
if workspace not in unique_workspaces.values():
unique_workspaces[path] = workspace
workspaces = unique_workspaces
# get number of detectors loaded - should be 4, but legacy data may contain less
loaded_detectors = {}
for ws_name in workspaces.values():
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.num_loaded_detectors[self.run] = num_loaded_detectors
self.last_loaded_runs.append(self.run)
return self.loaded_runs[self.run]
......@@ -89,11 +97,11 @@ def merge_workspaces(run, workspaces):
# initialise a group workspace
tmp = mantid.CreateSampleWorkspace()
overall_ws = mantid.GroupWorkspaces(tmp, OutputWorkspace=str(run))
# merge each workspace list in dectors into a single workspace
# merge each workspace list in detectors into a single workspace
for detector, workspace_list in iteritems(detectors):
if workspace_list:
# sort workspace list according to type_index
sorted_workspace_list = [None] * len(workspace_list)
sorted_workspace_list = [None] * num_files_per_detector
# sort workspace list according to type_index
for workspace in workspace_list:
data_type = workspace.rsplit("_")[1]
......@@ -117,43 +125,45 @@ def merge_workspaces(run, workspaces):
def create_merged_workspace(workspace_list):
if workspace_list:
# get max number of bins and max X range
num_workspaces = len(workspace_list)
max_num_bins = 0
for i in range(0, num_workspaces):
ws = mantid.mtd[workspace_list[i]]
max_num_bins = max(ws.blocksize(), max_num_bins)
for ws_name in workspace_list:
if ws_name:
ws = mantid.mtd[ws_name]
max_num_bins = max(ws.blocksize(), max_num_bins)
# create single ws for the merged data, use original ws as a template
merged_ws = mantid.WorkspaceFactory.create(mantid.mtd[workspace_list[0]], NVectors=num_workspaces,
template_ws = next(ws for ws in workspace_list if ws is not None)
merged_ws = mantid.WorkspaceFactory.create(mantid.mtd[template_ws], NVectors=num_files_per_detector,
XLength=max_num_bins, YLength=max_num_bins)
# create a merged workspace based on every entry from workspace list
for i in range(0, num_workspaces):
# load in ws
ws = mantid.mtd[workspace_list[i]]
# check if histogram data, and convert if necessary
if ws.isHistogramData():
ws = mantid.ConvertToPointData(InputWorkspace=ws.name(), OutputWorkspace=ws.name())
# find max x val
max_x = np.max(ws.readX(0))
# get current number of bins
num_bins = ws.blocksize()
# pad bins
X_padded = np.empty(max_num_bins)
X_padded.fill(max_x)
X_padded[:num_bins] = ws.readX(0)
Y_padded = np.zeros(max_num_bins)
Y_padded[:num_bins] = ws.readY(0)
E_padded = np.zeros(max_num_bins)
E_padded[:num_bins] = ws.readE(0)
# set row of merged workspace
merged_ws.setX(i, X_padded)
merged_ws.setY(i, Y_padded)
merged_ws.setE(i, E_padded)
# remove workspace from ADS
mantid.AnalysisDataService.remove(ws.getName())
for i in range(0, num_files_per_detector):
# load in ws - first check workspace exists
if workspace_list[i]:
ws = mantid.mtd[workspace_list[i]]
# check if histogram data, and convert if necessary
if ws.isHistogramData():
ws = mantid.ConvertToPointData(InputWorkspace=ws.name(), OutputWorkspace=ws.name())
# find max x val
max_x = np.max(ws.readX(0))
# get current number of bins
num_bins = ws.blocksize()
# pad bins
X_padded = np.empty(max_num_bins)
X_padded.fill(max_x)
X_padded[:num_bins] = ws.readX(0)
Y_padded = np.zeros(max_num_bins)
Y_padded[:num_bins] = ws.readY(0)
E_padded = np.zeros(max_num_bins)
E_padded[:num_bins] = ws.readE(0)
# set row of merged workspace
merged_ws.setX(i, X_padded)
merged_ws.setY(i, Y_padded)
merged_ws.setE(i, E_padded)
# remove workspace from ADS
mantid.AnalysisDataService.remove(ws.getName())
return merged_ws
......
......@@ -288,6 +288,15 @@ class ElementalAnalysisGui(QtWidgets.QMainWindow):
last_run = self.load_widget.last_loaded_run()
if last_run is None:
return
# check all detectors are loaded
for j, detector in enumerate(self.detectors.getNames()):
if j < self.load_widget.get_run_num_loaded_detectors(last_run):
self.detectors.enableDetector(detector)
else:
# disable checkbox and uncheck box
self.detectors.disableDetector(detector)
self.detectors.setStateQuietly(detector, False)
to_plot = deepcopy([det.isChecked() for det in self.detectors.detectors])
if self.plot_window is None and any(to_plot) is False:
return
......@@ -309,11 +318,11 @@ class ElementalAnalysisGui(QtWidgets.QMainWindow):
ws.setYUnit('Counts')
# find correct detector number from the workspace group run
if self.lines.total.isChecked():
self.plotting.plot(detector, ws.getName(), spec_num=spectrum_index["Total"], color=self.BLUE)
self.plotting.plot(detector, ws.name(), spec_num=spectrum_index["Total"], color=self.BLUE)
if self.lines.prompt.isChecked():
self.plotting.plot(detector, ws.getName(), spec_num=spectrum_index["Prompt"], color=self.ORANGE)
self.plotting.plot(detector, ws.name(), spec_num=spectrum_index["Prompt"], color=self.ORANGE)
if self.lines.delayed.isChecked():
self.plotting.plot(detector, ws.getName(), spec_num=spectrum_index["Delayed"], color=self.GREEN)
self.plotting.plot(detector, ws.name(), spec_num=spectrum_index["Delayed"], color=self.GREEN)
# add current selection of lines
for element in self.ptable.selection:
......@@ -427,9 +436,11 @@ class ElementalAnalysisGui(QtWidgets.QMainWindow):
def add_line_by_type(self, run, _type):
# Ensure all detectors are enabled
for detector in self.detectors.detectors:
if not detector.isEnabled():
detector.setEnabled(True)
last_run = self.load_widget.last_loaded_run()
for i, detector in enumerate(self.detectors.detectors):
if i < self.load_widget.get_run_num_loaded_detectors(last_run):
if not detector.isEnabled():
detector.setEnabled(True)
if self.plot_window is None:
return
......@@ -444,7 +455,7 @@ class ElementalAnalysisGui(QtWidgets.QMainWindow):
for subplot in self.plotting.get_subplots():
name = '{}; Detector {}'.format(run, subplot[-1])
ws = mantid.mtd[name]
self.plotting.plot(subplot, ws.getName(), spec_num=spectrum_index[_type], color=color)
self.plotting.plot(subplot, ws.name(), spec_num=spectrum_index[_type], color=color)
def remove_line_type(self, run, _type):
if self.plot_window is None:
......@@ -455,19 +466,21 @@ class ElementalAnalysisGui(QtWidgets.QMainWindow):
for subplot in self.plotting.get_subplots():
name = '{}; Detector {}'.format(run, subplot[-1])
ws = mantid.mtd[name]
self.plotting.remove_line(subplot, ws.getName(), spec=spectrum_index[_type])
self.plotting.remove_line(subplot, ws.name(), spec=spectrum_index[_type])
# If no line type is selected do not allow plotting
self.uncheck_detectors_if_no_line_plotted()
def uncheck_detectors_if_no_line_plotted(self):
last_run = self.load_widget.last_loaded_run()
if not any([
self.lines.total.isChecked(),
self.lines.prompt.isChecked(),
self.lines.delayed.isChecked()
]):
for detector in self.detectors.detectors:
detector.setEnabled(False)
for i, detector in enumerate(self.detectors.detectors):
if i < self.load_widget.get_run_num_loaded_detectors(last_run):
detector.setEnabled(False)
# When removing a line with the remove window uncheck the line here
def uncheck_on_removed(self, removed_lines):
......
......@@ -24,7 +24,6 @@ from MultiPlotting.multi_plotting_widget import MultiPlotWidget
from MultiPlotting.label import Label
@start_qapplication
class ElementalAnalysisTest(unittest.TestCase):
@classmethod
......@@ -268,7 +267,8 @@ class ElementalAnalysisTest(unittest.TestCase):
@mock.patch('Muon.GUI.ElementalAnalysis.Detectors.detectors_view.QtWidgets.QWidget')
def test_loading_finished_returns_correctly_if_no_plot_window_but_has_to_plot(self, mock_qwidget):
self.gui.load_widget.last_loaded_run = mock.Mock(return_value=['run1', 'run2', 'run3'])
self.gui.load_widget.last_loaded_run = mock.Mock(return_value=2695)
self.gui.load_widget.get_run_num_loaded_detectors = mock.Mock(return_value=4)
self.gui.detectors.getNames.return_value = ['1', '2', '3']
self.gui.plot_window = None
self.gui.plotting = mock.Mock()
......@@ -283,7 +283,8 @@ class ElementalAnalysisTest(unittest.TestCase):
@mock.patch('Muon.GUI.ElementalAnalysis.Detectors.detectors_view.QtWidgets.QWidget')
def test_loading_finished_returns_correctly_if_no_to_plot_but_has_plot_window(
self, mock_qwidget):
self.gui.load_widget.last_loaded_run = mock.Mock(return_value=['run1', 'run2', 'run3'])
self.gui.load_widget.last_loaded_run = mock.Mock(return_value=2695)
self.gui.load_widget.get_run_num_loaded_detectors = mock.Mock(return_value=4)
self.gui.detectors.getNames.return_value = ['1', '2', '3']
mock_qwidget.return_value = True
self.gui.plot_window = mock.Mock()
......@@ -291,6 +292,26 @@ class ElementalAnalysisTest(unittest.TestCase):
self.gui.loading_finished()
self.assertEqual(self.gui.plotting.remove_subplot.call_count, 3)
@mock.patch('Muon.GUI.ElementalAnalysis.Detectors.detectors_view.QtWidgets.QWidget')
def test_loading_finished_correctly_disables_detectors_if_less_detectors_are_loaded(
self, mock_qwidget):
num_loaded_detectors = 1
num_detectors = 4
self.gui.load_widget.last_loaded_run = mock.Mock(return_value=2695)
self.gui.load_widget.get_run_num_loaded_detectors = mock.Mock(return_value=num_loaded_detectors)
self.gui.detectors.getNames.return_value = ['1', '2', '3', '4']
self.gui.plotting.get_subplots.return_value = ['1', '2', '3', '4']
mock_qwidget.return_value = True
self.gui.plot_window = mock.Mock()
self.gui.loading_finished()
# should have set the states of num_detectors - num_loaded_detectors
self.assertEqual(self.gui.detectors.setStateQuietly.call_count,num_detectors-num_loaded_detectors)
# should have only enabled the detector we have loaded
self.assertEqual(self.gui.detectors.enableDetector.call_count, num_loaded_detectors)
# Should disable (num_detectors - num_loaded_detectors) detectors
self.assertEqual(self.gui.detectors.disableDetector.call_count, num_detectors-num_loaded_detectors)
@mock.patch('Muon.GUI.ElementalAnalysis.elemental_analysis.ElementalAnalysisGui.add_peak_data')
@mock.patch('Muon.GUI.ElementalAnalysis.elemental_analysis.mantid')
def test_add_detectors_to_plot_plots_all_given_ws_and_all_selected_elements(
......@@ -304,7 +325,7 @@ class ElementalAnalysisTest(unittest.TestCase):
self.gui.lines.total.isChecked.return_value = True
self.gui.lines.prompt.isChecked.return_value = False
self.gui.lines.delayed.isChecked.return_value = True
mock_mantid.mtd['name1'].getName.return_value = 'Detector 1'
mock_mantid.mtd['name1'].name.return_value = 'Detector 1'
self.gui.add_detector_to_plot('GE1', 'name1')
self.assertEqual(self.gui.plotting.add_subplot.call_count, 1)
self.assertEqual(self.gui.plotting.plot.call_count, 2)
......@@ -557,11 +578,11 @@ class ElementalAnalysisTest(unittest.TestCase):
'2695; Detector 2': mock.Mock(),
'2695; Detector 3': mock.Mock()
}
mock_mantid.mtd['2695; Detector 1'].getName.return_value = '2695; Detector 1'
mock_mantid.mtd['2695; Detector 2'].getName.return_value = '2695; Detector 2'
mock_mantid.mtd['2695; Detector 1'].name.return_value = '2695; Detector 1'
mock_mantid.mtd['2695; Detector 2'].name.return_value = '2695; Detector 2'
expected_calls = [
mock.call('1', '2695; Detector 1', color='C0',spec_num=spectrum_index['Total']),
mock.call('2', '2695; Detector 2', color='C0',spec_num=spectrum_index['Total'])
mock.call('1', '2695; Detector 1', color='C0', spec_num=spectrum_index['Total']),
mock.call('2', '2695; Detector 2', color='C0', spec_num=spectrum_index['Total'])
]
self.gui.add_line_by_type(2695, 'Total')
......@@ -585,8 +606,8 @@ class ElementalAnalysisTest(unittest.TestCase):
'2695; Detector 2': mock.Mock(),
'2695; Detector 3': mock.Mock()
}
mock_mantid.mtd['2695; Detector 1'].getName.return_value = '2695; Detector 1'
mock_mantid.mtd['2695; Detector 2'].getName.return_value = '2695; Detector 2'
mock_mantid.mtd['2695; Detector 1'].name.return_value = '2695; Detector 1'
mock_mantid.mtd['2695; Detector 2'].name.return_value = '2695; Detector 2'
expected_calls = [mock.call('1', '2695; Detector 1', spec=spectrum_index['Total']),
mock.call('2', '2695; Detector 2', spec=spectrum_index['Total'])]
self.gui.remove_line_type(2695, 'Total')
......
......@@ -85,7 +85,7 @@ class LoadUtilsTest(unittest.TestCase):
def test_create_merged_workspace(self):
workspace_list = []
num_workspaces = 5
num_workspaces = lutils.num_files_per_detector
workspace_names = []
num_bins = 100
X_data = np.linspace(0, 400, num_bins)
......@@ -93,7 +93,7 @@ class LoadUtilsTest(unittest.TestCase):
m = 0.1
Yfunc = lambda x, specNo: m * x + specNo
Efunc = lambda x, specNo: 2 * m * x + specNo
for i in range(0, 5):
for i in range(0, num_workspaces):
name = "test_" + str(i)
workspace_names.append(name)
ws = mantid.WorkspaceFactory.create("Workspace2D", NVectors=1,
......@@ -116,6 +116,41 @@ class LoadUtilsTest(unittest.TestCase):
self.assertTrue(np.array_equal(merged_ws.readY(i), Yfunc(X_data, i)))
self.assertTrue(np.array_equal(merged_ws.readE(i), Efunc(X_data, i)))
def test_merge_workspaces_returns_correctly_if_delayed_data_missing(self):
num_files_per_detector = lutils.num_files_per_detector
workspace_list = [None] * num_files_per_detector
num_bins = 100
X_data = np.linspace(0, 400, num_bins)
names = ["Total", "Prompt"]
# create data in each workspace based on y = mx + specNumber
Yfunc = lambda x, specNo: 0.1 * x + specNo
Efunc = lambda x, specNo: 2 * 0.1 * x + specNo
for i in range(0, 2):
name = names[i]
ws = mantid.WorkspaceFactory.create("Workspace2D", NVectors=1,
XLength=num_bins, YLength=num_bins)
mantid.mtd.add(name, ws)
Y_data = Yfunc(X_data, i)
E_data = Efunc(X_data, i)
ws.setY(0, Y_data)
ws.setX(0, X_data)
ws.setE(0, E_data)
input_index = lutils.spectrum_index[name] - 1
workspace_list[input_index] = name
merged_ws = lutils.create_merged_workspace(workspace_list)
self.assertEqual(merged_ws.getNumberHistograms(), num_files_per_detector)
# check that total and prompt data were copied to the correct place
for i in range(0, 2):
name = names[i]
input_index = lutils.spectrum_index[name] - 1
self.assertTrue(np.array_equal(merged_ws.readX(input_index), X_data))
self.assertTrue(np.array_equal(merged_ws.readY(input_index), Yfunc(X_data, i)))
self.assertTrue(np.array_equal(merged_ws.readE(input_index), Efunc(X_data, i)))
# check that the y data for delayed response is all zeros
self.assertTrue(not np.any(merged_ws.readY(lutils.spectrum_index["Delayed"]-1)))
def test_flatten_run_data(self):
test_workspaces = [mantid.CreateSampleWorkspace(OutputWorkspace=name) for name in self.test_ws_names]
workspaces = []
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment