Newer
Older
#pylint: disable=no-init
from mantid.kernel import *
from mantid.api import *
import EnggUtils
class EnggFocus(PythonAlgorithm):
Federico Montesino Pouzols
committed
INDICES_PROP_NAME = 'SpectrumNumbers'
def category(self):
Federico Montesino Pouzols
committed
return "Diffraction\\Engineering;PythonAlgorithms"
def name(self):
return "EnggFocus"
def summary(self):
return "Focuses a run by summing up all the spectra into a single one."
def PyInit(self):
self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", Direction.Input),
"Workspace with the run to focus.")
self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", Direction.Output),
Federico Montesino Pouzols
committed
"A workspace with focussed data")
self.declareProperty(MatrixWorkspaceProperty("VanadiumWorkspace", "", Direction.Input,
PropertyMode.Optional),
doc = 'Workspace with the Vanadium (correction and calibration) run. '
'Alternatively, when the Vanadium run has been already processed, '
'the properties can be used')
self.declareProperty(ITableWorkspaceProperty('VanIntegrationWorkspace', '',
Direction.Input, PropertyMode.Optional),
doc = 'Results of integrating the spectra of a Vanadium run, with one column '
'(integration result) and one row per spectrum. This can be used in '
'combination with OutVanadiumCurveFits from a previous execution and '
'VanadiumWorkspace to provide pre-calculated values for Vanadium correction.')
self.declareProperty(MatrixWorkspaceProperty('VanCurvesWorkspace', '', Direction.Input,
PropertyMode.Optional),
doc = 'A workspace2D with the fitting workspaces corresponding to '
'the instrument banks. This workspace has three spectra per bank, as produced '
'by the algorithm Fit. This is meant to be used as an alternative input '
'VanadiumWorkspace for testing and performance reasons. If not given, no '
'workspace is generated.')
self.declareProperty("Bank", '', StringListValidator(EnggUtils.ENGINX_BANKS),
Federico Montesino Pouzols
committed
direction=Direction.Input,
doc = "Which bank to focus: It can be specified as 1 or 2, or "
"equivalently, North or South. See also " + self.INDICES_PROP_NAME + " "
"for a more flexible alternative to select specific detectors")
self.declareProperty(self.INDICES_PROP_NAME, '', direction=Direction.Input,
Federico Montesino Pouzols
committed
doc = 'Sets the spectrum numbers for the detectors '
'that should be considered in the focussing operation (all others will be '
'ignored). This option cannot be used together with Bank, as they overlap. '
Federico Montesino Pouzols
committed
'You can give multiple ranges, for example: "0-99", or "0-9, 50-59, 100-109".')
self.declareProperty(ITableWorkspaceProperty('DetectorPositions', '', Direction.Input,
PropertyMode.Optional),
Federico Montesino Pouzols
committed
"Calibrated detector positions. If not specified, default ones are used.")
Federico Montesino Pouzols
committed
def PyExec(self):
# Get the run workspace
wks = self.getProperty('InputWorkspace').value
# Get spectra indices either from bank or direct list of indices, checking for errors
bank = self.getProperty('Bank').value
spectra = self.getProperty(self.INDICES_PROP_NAME).value
indices = EnggUtils.getWsIndicesFromInProperties(wks, bank, spectra)
# Leave the data for the bank we are interested in only
wks = EnggUtils.cropData(self, wks, indices)
prog = Progress(self, start=0, end=1, nreports=3)
prog.report('Preparing input workspace')
# Leave data for the same bank in the vanadium workspace too
vanWS = self.getProperty('VanadiumWorkspace').value
vanIntegWS = self.getProperty('VanIntegrationWorkspace').value
vanCurvesWS = self.getProperty('VanCurvesWorkspace').value
EnggUtils.applyVanadiumCorrections(self, wks, indices, vanWS, vanIntegWS, vanCurvesWS)
# Apply calibration
Federico Montesino Pouzols
committed
detPos = self.getProperty("DetectorPositions").value
if detPos:
self._applyCalibration(wks, detPos)
# Convert to dSpacing
wks = EnggUtils.convertToDSpacing(self, wks)
prog.report('Summing spectra')
# Sum the values
wks = EnggUtils.sumSpectra(self, wks)
prog.report('Preparing output workspace')
# Convert back to time of flight
wks = EnggUtils.convertToToF(self, wks)
# OpenGenie displays distributions instead of pure counts (this is done implicitly when
# converting units), so I guess that's what users will expect
self._convertToDistr(wks)
self.setProperty("OutputWorkspace", wks)
def _applyCalibration(self, wks, detPos):
Federico Montesino Pouzols
committed
"""
Refines the detector positions using the result of calibration (if one is specified).
@param wks :: workspace to apply the calibration (on its instrument)
Federico Montesino Pouzols
committed
@param detPos :: detector positions (as a table of positions, one row per detector)
Federico Montesino Pouzols
committed
alg = self.createChildAlgorithm('ApplyCalibration')
alg.setProperty('Workspace', wks)
Federico Montesino Pouzols
committed
alg.setProperty('PositionTable', detPos)
def _convertToDistr(self, wks):
"""
Federico Montesino Pouzols
committed
Convert workspace to distribution
@param wks :: workspace, which is modified/converted in place
Federico Montesino Pouzols
committed
alg = self.createChildAlgorithm('ConvertToDistribution')
alg.setProperty('Workspace', wks)
AlgorithmFactory.subscribe(EnggFocus)