-
Notifications
You must be signed in to change notification settings - Fork 122
/
DirectILLSelfShielding.py
186 lines (165 loc) · 9.91 KB
/
DirectILLSelfShielding.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# -*- coding: utf-8 -*-# Mantid Repository : https://github.com/mantidproject/mantid
#
# Copyright © 2018 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 +
import DirectILL_common as common
import ILL_utilities as utils
from mantid.api import (AlgorithmFactory, DataProcessorAlgorithm, InstrumentValidator,
MatrixWorkspaceProperty, PropertyMode, WorkspaceUnitValidator)
from mantid.kernel import (CompositeValidator, Direction, EnabledWhenProperty, IntBoundedValidator,
Property, PropertyCriterion, StringListValidator)
from mantid.simpleapi import (ConvertUnits, MonteCarloAbsorption)
class DirectILLSelfShielding(DataProcessorAlgorithm):
"""A workflow algorithm for self-shielding corrections."""
def __init__(self):
"""Initialize an instance of the algorithm."""
DataProcessorAlgorithm.__init__(self)
def category(self):
"""Return the algorithm's category."""
return common.CATEGORIES
def seeAlso(self):
return [ 'DirectILLApplySelfShielding', 'DirectILLReduction' ]
def name(self):
"""Return the algorithm's name."""
return 'DirectILLSelfShielding'
def summary(self):
"""Return a summary of the algorithm."""
return 'Calculates self-shielding correction for the direct geometry TOF spectrometers at ILL.'
def version(self):
"""Return the algorithm's version."""
return 1
def PyExec(self):
"""Execute the algorithm."""
self._subalgLogging = self.getProperty(common.PROP_SUBALG_LOGGING).value == common.SUBALG_LOGGING_ON
wsNamePrefix = self.getProperty(common.PROP_OUTPUT_WS).valueAsStr
cleanupMode = self.getProperty(common.PROP_CLEANUP_MODE).value
self._names = utils.NameSource(wsNamePrefix, cleanupMode)
self._cleanup = utils.Cleanup(cleanupMode, self._subalgLogging)
# Get input workspace.
mainWS = self._inputWS()
# Self shielding and empty container subtraction, if requested.
correctionWS = self._selfShielding(mainWS)
self._finalize(correctionWS)
def PyInit(self):
"""Initialize the algorithm's input and output properties."""
PROPGROUP_SIMULATION_INSTRUMENT = 'Simulation Instrument Settings'
positiveInt = IntBoundedValidator(lower=1)
greaterThanOneInt = IntBoundedValidator(lower=2)
greaterThanTwoInt = IntBoundedValidator(lower=3)
inputWorkspaceValidator = CompositeValidator()
inputWorkspaceValidator.add(InstrumentValidator())
inputWorkspaceValidator.add(WorkspaceUnitValidator('TOF'))
# Properties.
self.declareProperty(MatrixWorkspaceProperty(
name=common.PROP_INPUT_WS,
defaultValue='',
validator=inputWorkspaceValidator,
optional=PropertyMode.Optional,
direction=Direction.Input),
doc='A workspace for which to simulate the self shielding.')
self.declareProperty(MatrixWorkspaceProperty(name=common.PROP_OUTPUT_WS,
defaultValue='',
direction=Direction.Output),
doc='A workspace containing the self shielding correction factors.')
self.declareProperty(name=common.PROP_CLEANUP_MODE,
defaultValue=utils.Cleanup.ON,
validator=StringListValidator([
utils.Cleanup.ON,
utils.Cleanup.OFF]),
direction=Direction.Input,
doc='What to do with intermediate workspaces.')
self.declareProperty(name=common.PROP_SUBALG_LOGGING,
defaultValue=common.SUBALG_LOGGING_OFF,
validator=StringListValidator([
common.SUBALG_LOGGING_OFF,
common.SUBALG_LOGGING_ON]),
direction=Direction.Input,
doc='Enable or disable subalgorithms to print in the logs.')
self.declareProperty(name=common.PROP_SIMULATION_INSTRUMENT,
defaultValue=common.SIMULATION_INSTRUMEN_SPARSE,
validator=StringListValidator([
common.SIMULATION_INSTRUMEN_SPARSE,
common.SIMULATION_INSTRUMENT_FULL]),
direction=Direction.Input,
doc='Select if the simulation should be performed on full or approximated instrument.')
self.setPropertyGroup(common.PROP_SIMULATION_INSTRUMENT, PROPGROUP_SIMULATION_INSTRUMENT)
self.declareProperty(name=common.PROP_SPARSE_INSTRUMENT_ROWS,
defaultValue=5,
validator=greaterThanTwoInt,
direction=Direction.Input,
doc='Number of detector rows in sparse simulation instrument.')
self.setPropertyGroup(common.PROP_SPARSE_INSTRUMENT_ROWS, PROPGROUP_SIMULATION_INSTRUMENT)
self.setPropertySettings(common.PROP_SPARSE_INSTRUMENT_ROWS, EnabledWhenProperty(common.PROP_SIMULATION_INSTRUMENT,
PropertyCriterion.IsEqualTo, common.SIMULATION_INSTRUMEN_SPARSE))
self.declareProperty(name=common.PROP_SPARSE_INSTRUMENT_COLUMNS,
defaultValue=20,
validator=greaterThanOneInt,
direction=Direction.Input,
doc='Number of detector columns in sparse simulation instrument.')
self.setPropertyGroup(common.PROP_SPARSE_INSTRUMENT_COLUMNS, PROPGROUP_SIMULATION_INSTRUMENT)
self.setPropertySettings(common.PROP_SPARSE_INSTRUMENT_COLUMNS, EnabledWhenProperty(common.PROP_SIMULATION_INSTRUMENT,
PropertyCriterion.IsEqualTo, common.SIMULATION_INSTRUMEN_SPARSE))
self.declareProperty(name=common.PROP_NUMBER_OF_SIMULATION_WAVELENGTHS,
defaultValue=Property.EMPTY_INT,
validator=greaterThanTwoInt,
direction=Direction.Input,
doc='Number of wavelength points where the simulation is performed (no longer used).')
self.declareProperty(name=common.PROP_EVENTS_PER_WAVELENGTH,
defaultValue=300,
validator=positiveInt,
direction=Direction.Input,
doc='The number of neutron events to simulate per wavelength point.')
def validateInputs(self):
"""Check for issues with user input."""
return dict()
def _finalize(self, outWS):
"""Do final cleanup and set the output property."""
self.setProperty(common.PROP_OUTPUT_WS, outWS)
self._cleanup.cleanup(outWS)
self._cleanup.finalCleanup()
def _inputWS(self):
"""Return the raw input workspace."""
mainWS = self.getProperty(common.PROP_INPUT_WS).value
self._cleanup.protect(mainWS)
return mainWS
def _selfShielding(self, mainWS):
"""Return the self shielding corrections."""
wavelengthWSName = self._names.withSuffix('input_in_wavelength')
wavelengthWS = ConvertUnits(InputWorkspace=mainWS,
OutputWorkspace=wavelengthWSName,
Target='Wavelength',
EMode='Direct',
EnableLogging=self._subalgLogging)
eventsPerPoint =self.getProperty(common.PROP_EVENTS_PER_WAVELENGTH).value
correctionWSName = self._names.withSuffix('correction')
useFullInstrument = self.getProperty(common.PROP_SIMULATION_INSTRUMENT).value == common.SIMULATION_INSTRUMENT_FULL
if useFullInstrument:
correctionWS = MonteCarloAbsorption(InputWorkspace=wavelengthWS,
OutputWorkspace=correctionWSName,
SparseInstrument=False,
Interpolation='CSpline',
EnableLogging=self._subalgLogging,
EventsPerPoint=eventsPerPoint,
SeedValue=common.SIMULATION_SEED)
else:
rows = self.getProperty(common.PROP_SPARSE_INSTRUMENT_ROWS).value
columns = self.getProperty(common.PROP_SPARSE_INSTRUMENT_COLUMNS).value
correctionWS = MonteCarloAbsorption(InputWorkspace=wavelengthWS,
OutputWorkspace=correctionWSName,
SparseInstrument=True,
NumberOfDetectorRows=rows,
NumberOfDetectorColumns=columns,
Interpolation='CSpline',
EnableLogging=self._subalgLogging,
EventsPerPoint=eventsPerPoint,
SeedValue=common.SIMULATION_SEED)
self._cleanup.cleanup(wavelengthWS)
correctionWS = ConvertUnits(InputWorkspace=correctionWS,
OutputWorkspace=correctionWSName,
Target='TOF',
EMode='Direct',
EnableLogging=self._subalgLogging)
return correctionWS
AlgorithmFactory.subscribe(DirectILLSelfShielding)