Skip to content
Snippets Groups Projects
ReflectometryReductionOneLiveData.py 6.21 KiB
Newer Older
from __future__ import (absolute_import, division, print_function)

from mantid.simpleapi import *
from mantid.kernel import *
from mantid.api import *


class LiveValue():
    def __init__(self, value, unit):
        self.value = value
        self.unit = unit


class ReflectometryReductionOneLiveData(DataProcessorAlgorithm):
    def category(self):
        return 'Reflectometry'

    def summary(self):
        return 'Run the reflectometry reduction algorithm on live data'

    def seeAlso(self):
        return [ "ReflectometryReductionOneAuto", "StartLiveData" ]

    def PyInit(self):
        self.copyProperties('ReflectometryReductionOneAuto',[
            'InputWorkspace', 'SummationType', 'ReductionType','IncludePartialBins', 'AnalysisMode',
            'ProcessingInstructions','CorrectDetectors',
            'DetectorCorrectionType','WavelengthMin','WavelengthMax','I0MonitorIndex',
            'MonitorBackgroundWavelengthMin','MonitorBackgroundWavelengthMax',
            'MonitorIntegrationWavelengthMin','MonitorIntegrationWavelengthMax',
            'NormalizeByIntegratedMonitors','FirstTransmissionRun',
            'SecondTransmissionRun','Params','StartOverlap','EndOverlap',
            'StrictSpectrumChecking','CorrectionAlgorithm','Polynomial','C0','C1',
            'MomentumTransferMin','MomentumTransferStep','MomentumTransferMax',
            'PolarizationAnalysis','Pp','Ap','Rho','Alpha','Debug','OutputWorkspace'])

    def validateInputs(self):
        issues = {}
        return issues

Gemma Guest's avatar
Gemma Guest committed
    def PyExec(self):
        self.setupWorkspaceForReduction()
        alg = self.setupReductionAlgorithm()
        self.runReductionAlgorithm(alg)

    def setupWorkspaceForReduction(self):
        """Set up the workspace ready for the reduction"""
        self.createWorkspaceForReduction()
        self.setupInstrument()
        liveValues = self.getLiveValuesFromInstrument()
        self.setupSampleLogs(liveValues)
        self.setupSlits(liveValues)

    def setupReductionAlgorithm(self):
        """Set up the reduction algorithm"""
        alg = AlgorithmManager.create("ReflectometryReductionOneAuto")
        alg.initialize()
        alg.setChild(True)
Gemma Guest's avatar
Gemma Guest committed
        self.copyPropertyValuesTo(alg)
        alg.setProperty("InputWorkspace", self.ws_name)
        alg.setProperty("ThetaLogName", "Theta")
        alg.setProperty("OutputWorkspaceBinned", self.ws_name)
        return alg

    def runReductionAlgorithm(self, alg):
        """Run the reduction"""
        alg.execute()
        out_ws = alg.getProperty("OutputWorkspaceBinned").value
        self.setProperty("OutputWorkspace", out_ws)

    def createWorkspaceForReduction(self):
        """Create a workspace for the input/output to the reduction algorithm"""
        in_ws_name = self.getProperty("InputWorkspace").value.getName()
        self.ws_name = self.getPropertyValue("OutputWorkspace")
        CloneWorkspace(InputWorkspace=in_ws_name,OutputWorkspace=self.ws_name)
Gemma Guest's avatar
Gemma Guest committed
    def setupInstrument(self):
        """Sets the instrument name and loads the instrument on the workspace"""
        self.instrument = config.getInstrument().shortName()
        LoadInstrument(Workspace=self.ws_name,RewriteSpectraMap=True,InstrumentName=self.instrument)

    def setupSampleLogs(self, liveValues):
        """Set up the sample logs based on live values from the instrument"""
        logNames = [key for key in liveValues]
        logValues = [liveValues[key].value for key in liveValues]
        logUnits = [liveValues[key].unit for key in liveValues]
        AddSampleLogMultiple(Workspace=self.ws_name,LogNames=logNames,LogValues=logValues,
                             LogUnits=logUnits)

    def setupSlits(self, liveValues):
        """Set up instrument parameters for the slits"""
        s1 = liveValues[self.s1vgName()].value
        s2 = liveValues[self.s2vgName()].value
        SetInstrumentParameter(Workspace=self.ws_name,
                               ParameterName='vertical gap',
                               ParameterType='Number',
                               ComponentName='slit1',
                               Value=str(s1))
Gemma Guest's avatar
Gemma Guest committed
        SetInstrumentParameter(Workspace=self.ws_name,
                               ParameterName='vertical gap',
                               ParameterType='Number',
                               ComponentName='slit2',
                               Value=str(s2))

Gemma Guest's avatar
Gemma Guest committed
    def copyPropertyValuesTo(self, alg):
        props = self.getProperties()
        for prop in props:
            value = self.getPropertyValue(prop.name)
            alg.setPropertyValue(prop.name, value)
Gemma Guest's avatar
Gemma Guest committed
    def getLiveValuesFromInstrument(self):
        # get values from instrument
Gemma Guest's avatar
Gemma Guest committed
        liveValues = self.liveValueList()
        for key in liveValues:
            if liveValues[key].value is None:
Gemma Guest's avatar
Gemma Guest committed
                liveValues[key].value = self.getLiveValueFromInstrument(key)
        # check we have all we need
        self.validateLiveValues(liveValues)
        return liveValues

Gemma Guest's avatar
Gemma Guest committed
    def s1vgName(self):
        if self.instrument == 'INTER' or self.instrument == 'SURF':
            return 'S1VG'
        elif self.instrument == 'OFFSPEC':
            return 's1vgap'
        else:
            return 's1vg'

    def s2vgName(self):
        if self.instrument == 'INTER' or self.instrument == 'SURF':
            return 'S2VG'
        elif self.instrument == 'OFFSPEC':
            return 's2vgap'
        else:
            return 's2vg'

    def liveValueList(self):
        """Get the list of required live value names and their unit type"""
        liveValues =  {'Theta' : LiveValue(None, 'deg'),
                       self.s1vgName() : LiveValue(None, 'm'),
                       self.s2vgName() : LiveValue(None, 'm')}
        return liveValues
Gemma Guest's avatar
Gemma Guest committed
    def getLiveValueFromInstrument(self, logName):
        from epics import caget
        return caget('IN:' + self.instrument + ':CS:SB:' + logName, as_string=True)
Gemma Guest's avatar
Gemma Guest committed
    def validateLiveValues(self, liveValues):
        for key in liveValues:
            if liveValues[key].value is None:
                raise RuntimeError('Required value ' + key + ' was not found for instrument')
        if float(liveValues['Theta'].value) <= 1e-06:
            raise RuntimeError('Theta must be greater than zero')

AlgorithmFactory.subscribe(ReflectometryReductionOneLiveData)