ReflectometryISISPreprocess.py 4.55 KB
Newer Older
1
2
3
4
5
6
7
# -*- coding: utf-8 -*-# Mantid Repository : https://github.com/mantidproject/mantid
#
# Copyright © 2021 ISIS Rutherford Appleton Laboratory UKRI,
#   NScD Oak Ridge National Laboratory, European Spallation Source,
#   Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
# SPDX - License - Identifier: GPL - 3.0 +

8
9
from mantid.api import (AlgorithmFactory, DataProcessorAlgorithm, MatrixWorkspaceProperty, MatrixWorkspace,
                        PropertyMode, WorkspaceGroup)
10
11
from mantid.kernel import (CompositeValidator, StringArrayLengthValidator, StringArrayMandatoryValidator,
                           StringArrayProperty, Direction)
12
13
14


class ReflectometryISISPreprocess(DataProcessorAlgorithm):
15
16
17
    _RUNS = 'InputRunList'
    _GROUP_TOF = 'GroupTOFWorkspaces'
    _OUTPUT_WS = 'OutputWorkspace'
18
    _MONITOR_WS = 'MonitorWorkspace'
19
    _EVENT_MODE = "EventMode"
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

    def __init__(self):
        """Initialize an instance of the algorithm."""
        DataProcessorAlgorithm.__init__(self)

    def category(self):
        """Return the categories of the algorithm."""
        return 'ISIS\\Reflectometry;Workflow\\Reflectometry'

    def name(self):
        """Return the name of the algorithm."""
        return 'ReflectometryISISPreprocess'

    def summary(self):
        """Return a summary of the algorithm."""
        return "Preprocess ISIS reflectometry data, including optional loading and summing of the input runs."

    def seeAlso(self):
        """Return a list of related algorithm names."""
        return ['ReflectometryISISLoadAndProcess', 'ReflectometryReductionOneAuto']

    def PyInit(self):
42
43
44
45
46
47
48
49
50
        self.declareProperty(
            StringArrayProperty(self._RUNS, values=[], validator=self._get_input_runs_validator()),
            doc='A list of run numbers or workspace names to load and preprocess')
        self.declareProperty(self._EVENT_MODE, False, direction=Direction.Input,
                             doc='If true, load the input workspaces as event data')
        self.declareProperty(
            MatrixWorkspaceProperty(self._OUTPUT_WS, '', direction=Direction.Output),
            doc='The preprocessed output workspace. If multiple input runs are specified '
                'they will be summed into a single output workspace.')
51
52
53
        self.declareProperty(
            MatrixWorkspaceProperty(self._MONITOR_WS, '', direction=Direction.Output, optional=PropertyMode.Optional),
            doc='The loaded monitors workspace. This is only output in event mode.')
54

55
    def PyExec(self):
56
        workspace, monitor_ws = self._loadRun(self.getPropertyValue(self._RUNS))
57
        self.setProperty(self._OUTPUT_WS, workspace)
58
59
        if monitor_ws:
            self.setProperty(self._MONITOR_WS, monitor_ws)
60

61
62
63
64
65
66
67
68
    @staticmethod
    def _get_input_runs_validator():
        mandatoryInputRuns = CompositeValidator()
        mandatoryInputRuns.add(StringArrayMandatoryValidator())
        lenValidator = StringArrayLengthValidator()
        lenValidator.setLengthMin(1)
        mandatoryInputRuns.add(lenValidator)
        return mandatoryInputRuns
69

70
    def _loadRun(self, run: str) -> MatrixWorkspace:
71
72
73
        """Load a run as an event workspace if slicing is requested, or a histogram
        workspace otherwise. Transmission runs are always loaded as histogram workspaces."""
        event_mode = self.getProperty(self._EVENT_MODE).value
74
        monitor_ws = None
75
        if event_mode:
76
77
78
            alg = self.createChildAlgorithm('LoadEventNexus', Filename=run, LoadMonitors=True)
            alg.execute()
            ws = alg.getProperty('OutputWorkspace').value
79
            monitor_ws = alg.getProperty('MonitorWorkspace').value
80
81
82
            self._validate_event_ws(ws)
            self.log().information('Loaded event workspace')
        else:
83
84
85
            alg = self.createChildAlgorithm('LoadNexus', Filename=run)
            alg.execute()
            ws = alg.getProperty('OutputWorkspace').value
86
            self.log().information('Loaded workspace ')
87
        return ws, monitor_ws
88
89
90
91
92
93
94
95
96
97

    @staticmethod
    def _validate_event_ws(workspace):
        if isinstance(workspace, WorkspaceGroup):
            # Our reduction algorithm doesn't currently support this due to slicing
            # (which would result in a group of groups)
            raise RuntimeError('Loading Workspace Groups in event mode is not supported currently.')
        if not workspace.run().hasProperty('proton_charge'):
            # Reduction algorithm requires proton_charge
            raise RuntimeError('Event workspaces must contain proton_charge')
98
99
100


AlgorithmFactory.subscribe(ReflectometryISISPreprocess)