/
EQSANSNormalise.py
183 lines (157 loc) · 8.08 KB
/
EQSANSNormalise.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
# 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 +
# pylint: disable=no-init
import os
from mantid.api import *
from mantid.kernel import *
from reduction_workflow.find_data import find_file
class EQSANSNormalise(PythonAlgorithm):
"""
Normalise detector counts by accelerator current and beam spectrum.
"""
def category(self):
return "Workflow\\SANS\\UsesPropertyManager"
def name(self):
return "EQSANSNormalise"
def summary(self):
return "Normalise detector counts by accelerator current and beam spectrum"
def PyInit(self):
self.declareProperty(MatrixWorkspaceProperty("InputWorkspace", "", direction=Direction.Input))
self.declareProperty("NormaliseToBeam", True, "If true, the data will also be normalise by the beam profile")
self.declareProperty(
FileProperty("BeamSpectrumFile", "", action=FileAction.OptionalLoad),
"Beam spectrum to be used for normalisation [takes precedence over default]",
)
self.declareProperty("NormaliseToMonitor", False, "If true, the algorithm will look for a monitor workspace to use")
self.declareProperty(
"ReductionProperties",
"__sans_reduction_properties",
validator=StringMandatoryValidator(),
doc="Property manager name for the reduction",
)
self.declareProperty(MatrixWorkspaceProperty("OutputWorkspace", "", direction=Direction.Output))
self.declareProperty("OutputMessage", "", direction=Direction.Output, doc="Output message")
def PyExec(self):
# If we need to normalise by monitor, skip all other options
if self.getProperty("NormaliseToMonitor").value:
return self._normalise_to_monitor()
workspace = self.getProperty("InputWorkspace").value
output_ws_name = self.getPropertyValue("OutputWorkspace")
flux_data_path = None
if self.getProperty("NormaliseToBeam").value:
# If a spectrum file was supplied, check if it's a valid file path
beam_spectrum_file = self.getPropertyValue("BeamSpectrumFile").strip()
if len(beam_spectrum_file):
if os.path.isfile(beam_spectrum_file):
flux_data_path = beam_spectrum_file
else:
Logger("EQSANSNormalise").error("%s is not a file" % beam_spectrum_file)
else:
flux_files = find_file(filename="bl6_flux_at_sample", data_dir=None)
if len(flux_files) > 0:
flux_data_path = flux_files[0]
Logger("EQSANSNormalise").notice("Using beam flux file: %s" % flux_data_path)
else:
Logger("EQSANSNormalise").notice("Could not find beam flux file!")
if flux_data_path is not None:
beam_flux_ws_name = "__beam_flux"
alg = AlgorithmManager.create("LoadAscii")
alg.initialize()
alg.setChild(True)
alg.setProperty("Filename", flux_data_path)
alg.setProperty("OutputWorkspace", beam_flux_ws_name)
alg.setProperty("Separator", "Tab")
alg.setProperty("Unit", "Wavelength")
alg.execute()
beam_flux_ws = alg.getProperty("OutputWorkspace").value
alg = AlgorithmManager.create("ConvertToHistogram")
alg.initialize()
alg.setChild(True)
alg.setProperty("InputWorkspace", beam_flux_ws)
alg.setProperty("OutputWorkspace", beam_flux_ws_name)
alg.execute()
beam_flux_ws = alg.getProperty("OutputWorkspace").value
alg = AlgorithmManager.create("RebinToWorkspace")
alg.initialize()
alg.setChild(True)
alg.setProperty("WorkspaceToRebin", beam_flux_ws)
alg.setProperty("WorkspaceToMatch", workspace)
alg.setProperty("OutputWorkspace", beam_flux_ws_name)
alg.execute()
beam_flux_ws = alg.getProperty("OutputWorkspace").value
alg = AlgorithmManager.create("NormaliseToUnity")
alg.initialize()
alg.setChild(True)
alg.setProperty("InputWorkspace", beam_flux_ws)
alg.setProperty("OutputWorkspace", beam_flux_ws_name)
alg.execute()
beam_flux_ws = alg.getProperty("OutputWorkspace").value
alg = AlgorithmManager.create("Divide")
alg.initialize()
alg.setChild(True)
alg.setProperty("LHSWorkspace", workspace)
alg.setProperty("RHSWorkspace", beam_flux_ws)
alg.setProperty("OutputWorkspace", beam_flux_ws_name)
alg.execute()
workspace = alg.getProperty("OutputWorkspace").value
workspace.getRun().addProperty("beam_flux_ws", beam_flux_ws_name, True)
else:
flux_data_path = "Could not find beam flux file!"
alg = AlgorithmManager.create("NormaliseByCurrent")
alg.initialize()
alg.setChild(True)
alg.setProperty("InputWorkspace", workspace)
alg.setProperty("OutputWorkspace", output_ws_name)
alg.execute()
workspace = alg.getProperty("OutputWorkspace").value
workspace_name = alg.getPropertyValue("OutputWorkspace")
self.setProperty(
"OutputMessage", "Data [%s] normalized to accelerator current\n Beam flux file: %s" % (workspace_name, str(flux_data_path))
)
self.setProperty("OutputWorkspace", workspace)
def _normalise_to_monitor(self):
"""
Normalize
"""
input_ws_name = self.getPropertyValue("InputWorkspace")
output_ws_name = self.getPropertyValue("OutputWorkspace")
prop_mng = self.getPropertyValue("ReductionProperties")
reference_flux = self.getPropertyValue("BeamSpectrumFile").strip()
monitor_ws_name = input_ws_name + "_monitors"
if AnalysisDataService.doesExist(monitor_ws_name):
alg = AlgorithmManager.create("EQSANSMonitorTOF")
alg.initialize()
alg.setChild(True)
alg.setProperty("InputWorkspace", monitor_ws_name)
alg.setProperty("OutputWorkspace", monitor_ws_name + "_tof")
alg.execute()
monitor_ws = alg.getProperty("OutputWorkspace").value
alg = AlgorithmManager.create("ConvertUnits")
alg.initialize()
alg.setChild(True)
alg.setProperty("InputWorkspace", monitor_ws)
alg.setProperty("OutputWorkspace", monitor_ws_name + "_wl")
alg.setProperty("Target", "Wavelength")
alg.execute()
monitor_ws = alg.getProperty("OutputWorkspace").value
alg = AlgorithmManager.create("SANSBeamFluxCorrection")
alg.initialize()
alg.setChild(True)
alg.setProperty("InputWorkspace", input_ws_name)
alg.setProperty("InputMonitorWorkspace", monitor_ws)
alg.setProperty("ReferenceFluxFilename", reference_flux)
alg.setProperty("ReductionProperties", prop_mng)
alg.setProperty("OutputWorkspace", output_ws_name)
alg.execute()
output_msg = alg.getPropertyValue("OutputMessage")
output_ws = alg.getProperty("OutputWorkspace").value
self.setProperty("OutputWorkspace", output_ws)
self.setProperty("OutputMessage", "Data [%s] normalized to monitor\n %s" % (input_ws_name, output_msg))
else:
self.setProperty("OutputMessage", "Monitor not available. Data [%s] NOT normalized to monitor" % (input_ws_name))
#############################################################################################
AlgorithmFactory.subscribe(EQSANSNormalise)