Skip to content
Snippets Groups Projects
Commit fc00c351 authored by Harriet Brown's avatar Harriet Brown
Browse files

Make MergeWorkspacesWithLimits more suitable for general use

This commit modifies the MergeWorkspacesWithLimits algorithm to be usable
outside of the polaris scripts. The changes to the algorithm are as follows:

- Fixing the ADSValidator export to python.
- The Algorithm can now accept a group workspace, a multi-specta workspace, or a list of workspaces.
- The Algorithm can take an input use with MatchSpectra for if the scale or offset should be calculated

Re: #27445
parent edbaaca3
No related merge requests found
...@@ -16,9 +16,10 @@ using namespace boost::python; ...@@ -16,9 +16,10 @@ using namespace boost::python;
/// This is the base TypedValidator for most of the WorkspaceValidators /// This is the base TypedValidator for most of the WorkspaceValidators
void export_ADSValidator() { void export_ADSValidator() {
TypedValidatorExporter<std::string>::define("StringTypedValidator"); TypedValidatorExporter<std::vector<std::string>>
::define("StringTypedValidator");
class_<ADSValidator, bases<TypedValidator<std::string>>, boost::noncopyable>( class_<ADSValidator, bases<TypedValidator<std::vector<std::string>>>, boost::noncopyable>(
"ADSValidator", init<>("Default constructor")) "ADSValidator", init<>("Default constructor"))
.def(init<const bool, const bool>( .def(init<const bool, const bool>(
"Constructor setting allowMultiple and isOptional.", "Constructor setting allowMultiple and isOptional.",
......
...@@ -6,9 +6,12 @@ ...@@ -6,9 +6,12 @@
# SPDX - License - Identifier: GPL - 3.0 + # SPDX - License - Identifier: GPL - 3.0 +
from __future__ import (absolute_import, division, print_function) from __future__ import (absolute_import, division, print_function)
from mantid.simpleapi import (ConjoinWorkspaces, CropWorkspaceRagged, DeleteWorkspace, MatchSpectra, Rebin, SumSpectra) from mantid.simpleapi import (AnalysisDataService, CloneWorkspace, ConjoinWorkspaces, CropWorkspaceRagged,
from mantid.api import (DataProcessorAlgorithm, AlgorithmFactory, WorkspaceProperty, WorkspaceGroupProperty) DeleteWorkspace, GroupWorkspaces, MatchSpectra, Rebin, SumSpectra)
from mantid.kernel import (Direction, FloatArrayProperty) from mantid.api import (AlgorithmFactory, DataProcessorAlgorithm, WorkspaceProperty, WorkspaceGroup,
WorkspaceGroupProperty, ADSValidator)
from mantid.dataobjects import Workspace2D
from mantid.kernel import (Direction, FloatArrayProperty, StringArrayProperty)
import numpy as np import numpy as np
...@@ -36,66 +39,109 @@ class MergeWorkspacesWithLimits(DataProcessorAlgorithm): ...@@ -36,66 +39,109 @@ class MergeWorkspacesWithLimits(DataProcessorAlgorithm):
# given workspaces must exist # given workspaces must exist
# and must be public of ExperimentInfo # and must be public of ExperimentInfo
issues = dict() issues = dict()
ws_group = self.getProperty('InputWorkspaces').value ws_list = self.getProperty('InputWorkspaces').value
if not self.validate_ws(ws_list):
issues['InputWorkspaces'] = 'InputWorkspaces is not a list of workspaces or group workspace'
spectra_count = 0
for name_in_list in ws_list:
ws_in_list = AnalysisDataService.retrieve(name_in_list)
if type(ws_in_list) == Workspace2D:
spectra_count += ws_in_list.getNumberHistograms()
if type(ws_in_list) == WorkspaceGroup:
for ws_in_group in ws_in_list:
spectra_count += ws_in_group.getNumberHistograms()
x_min = self.getProperty('XMin').value x_min = self.getProperty('XMin').value
if not x_min.size == spectra_count:
issues['XMin'] = 'XMin entries does not match size of workspace group'
x_max = self.getProperty('XMax').value x_max = self.getProperty('XMax').value
if not x_min.size == ws_group.size(): if not x_max.size == spectra_count:
issues['x_min'] = 'x_min entries does not match size of workspace group' issues['XMax'] = 'XMax entries does not match size of workspace group'
if not x_max.size == ws_group.size():
issues['x_max'] = 'x_max entries does not match size of workspace group'
return issues return issues
@staticmethod
def validate_ws(ws_in):
for ws in ws_in:
try:
AnalysisDataService.retrieve(ws)
except KeyError:
return False
return True
def PyInit(self): def PyInit(self):
self.declareProperty(WorkspaceGroupProperty('InputWorkspaces', '', direction=Direction.Input), self.declareProperty(StringArrayProperty('InputWorkspaces', direction=Direction.Input, validator=ADSValidator()),
doc='The group workspace containing workspaces to be merged.') doc='List of workspaces or group workspace containing workspaces to be merged.')
self.declareProperty(WorkspaceProperty('OutputWorkspace', '', direction=Direction.Output), self.declareProperty(WorkspaceProperty('OutputWorkspace', '', direction=Direction.Output),
doc='The merged workspace') doc='The merged workspace.')
self.declareProperty(FloatArrayProperty('XMin', [],), self.declareProperty(FloatArrayProperty('XMin', [], direction=Direction.Input),
doc='Array of minimum X values for each workspace') doc='Array of minimum X values for each workspace.')
self.declareProperty(FloatArrayProperty('XMax', [],), self.declareProperty(FloatArrayProperty('XMax', [], direction=Direction.Input),
doc='Array of maximum X values for each workspace') doc='Array of maximum X values for each workspace.')
self.declareProperty('CalculateScale', True,
doc='Calculate scale factor when matching spectra.')
self.declareProperty('CalculateOffset', True,
doc='Calculate vertical shift when matching spectra.')
def PyExec(self): def PyExec(self):
ws_group = self.getProperty('InputWorkspaces').value ws_list = self.getProperty('InputWorkspaces').value
x_min = self.getProperty('XMin').value x_min = self.getProperty('XMin').value
x_max = self.getProperty('XMax').value x_max = self.getProperty('XMax').value
largest_range_spectrum, rebin_param = self.get_common_bin_range_and_largest_spectra(ws_group) scale_bool = self.getProperty('CalculateScale').value
ws_group = Rebin(InputWorkspace=ws_group, offset_bool = self.getProperty('CalculateOffset').value
Params=rebin_param, flattened_list = self.unwrap_groups(ws_list)
StoreInADS=False) largest_range_spectrum, rebin_param = self.get_common_bin_range_and_largest_spectra(flattened_list)
while ws_group.size() > 1: CloneWorkspace(InputWorkspace=flattened_list[0], OutputWorkspace='ws_conjoined')
ConjoinWorkspaces(InputWorkspace1=ws_group[0], Rebin(InputWorkspace='ws_conjoined', OutputWorkspace='ws_conjoined', Params=rebin_param)
InputWorkspace2=ws_group[1], for ws in flattened_list[1:]:
temp = CloneWorkspace(InputWorkspace=ws)
temp = Rebin(InputWorkspace=temp, Params=rebin_param)
ConjoinWorkspaces(InputWorkspace1='ws_conjoined',
InputWorkspace2=temp,
CheckOverlapping=False) CheckOverlapping=False)
ws_conjoined = AnalysisDataService.retrieve('ws_conjoined')
ws_conjoined, offset, scale, chisq = MatchSpectra(InputWorkspace=ws_group[0], ref_spec = ws_conjoined.getSpectrum(largest_range_spectrum).getSpectrumNo()
ReferenceSpectrum=largest_range_spectrum, ws_conjoined, offset, scale, chisq = MatchSpectra(InputWorkspace=ws_conjoined,
CalculateScale=False) ReferenceSpectrum=ref_spec,
CalculateScale=scale_bool,
CalculateOffset=offset_bool)
x_min, x_max, bin_width = self.fit_x_lims_to_match_histogram_bins(ws_conjoined, x_min, x_max) x_min, x_max, bin_width = self.fit_x_lims_to_match_histogram_bins(ws_conjoined, x_min, x_max)
ws_conjoined = CropWorkspaceRagged(InputWorkspace=ws_conjoined, XMin=x_min, XMax=x_max) ws_conjoined = CropWorkspaceRagged(InputWorkspace=ws_conjoined, XMin=x_min, XMax=x_max)
ws_conjoined = Rebin(InputWorkspace=ws_conjoined, Params=[min(x_min), bin_width, max(x_max)]) ws_conjoined = Rebin(InputWorkspace=ws_conjoined, Params=[min(x_min), bin_width, max(x_max)])
merged_ws = SumSpectra(InputWorkspace=ws_conjoined, WeightedSum=True, MultiplyBySpectra=False, StoreInADS=False) merged_ws = SumSpectra(InputWorkspace=ws_conjoined, WeightedSum=True, MultiplyBySpectra=False, StoreInADS=False)
DeleteWorkspace(ws_group)
DeleteWorkspace(ws_conjoined) DeleteWorkspace(ws_conjoined)
self.setProperty('OutputWorkspace', merged_ws) self.setProperty('OutputWorkspace', merged_ws)
def unwrap_groups(self, inputs):
output = []
for name_in_list in inputs:
ws_in_list = AnalysisDataService.retrieve(name_in_list)
if type(ws_in_list) == Workspace2D:
output.append(ws_in_list)
if type(ws_in_list) == WorkspaceGroup:
for ws_in_group in ws_in_list:
output.append(ws_in_group)
return output
@staticmethod @staticmethod
def get_common_bin_range_and_largest_spectra(ws_group): def get_common_bin_range_and_largest_spectra(ws_list):
x_min = np.inf x_min = np.inf
x_max = -np.inf x_max = -np.inf
x_num = -np.inf x_num = -np.inf
ws_max_range = 0 ws_max_range = 0
largest_range_spectrum = 0 largest_range_spectrum = 0
for i in range(ws_group.size()): for i in range(len(ws_list)):
x_data = ws_group[i].dataX(0) for j in range(ws_list[i].getNumberHistograms()):
x_min = min(np.min(x_data), x_min) x_data = ws_list[i].dataX(j)
x_max = max(np.max(x_data), x_max) x_min = min(np.min(x_data), x_min)
x_num = max(x_data.size, x_num) x_max = max(np.max(x_data), x_max)
ws_range = np.max(x_data) - np.min(x_data) x_num = max(x_data.size, x_num)
if ws_range > ws_max_range: ws_range = np.max(x_data) - np.min(x_data)
largest_range_spectrum = i + 1 if ws_range > ws_max_range:
ws_max_range = ws_range largest_range_spectrum = i
ws_max_range = ws_range
if x_min.any() == -np.inf or x_min.any() == np.inf: if x_min.any() == -np.inf or x_min.any() == np.inf:
raise AttributeError("Workspace x range contains an infinite value.") raise AttributeError("Workspace x range contains an infinite value.")
return largest_range_spectrum, [x_min, (x_max - x_min) / x_num, x_max] return largest_range_spectrum, [x_min, (x_max - x_min) / x_num, x_max]
......
...@@ -105,7 +105,8 @@ def generate_ts_pdf(run_number, focus_file_path, merge_banks=False, q_lims=None, ...@@ -105,7 +105,8 @@ def generate_ts_pdf(run_number, focus_file_path, merge_banks=False, q_lims=None,
if merge_banks: if merge_banks:
q_min, q_max = _load_qlims(q_lims) q_min, q_max = _load_qlims(q_lims)
merged_ws = mantid.MergeWorkspacesWithLimits(InputWorkspaces=focused_ws, XMin=q_min, XMax=q_max) merged_ws = mantid.MergeWorkspacesWithLimits(InputWorkspaces=focused_ws, XMin=q_min, XMax=q_max,
CalculateScale=False)
pdf_output = mantid.PDFFourierTransform(Inputworkspace=merged_ws, InputSofQType="S(Q)-1", PDFType="G(r)", pdf_output = mantid.PDFFourierTransform(Inputworkspace=merged_ws, InputSofQType="S(Q)-1", PDFType="G(r)",
Filter=True) Filter=True)
else: else:
......
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