-
Notifications
You must be signed in to change notification settings - Fork 122
/
msg_reducer.py
218 lines (196 loc) · 8.89 KB
/
msg_reducer.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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# msg_reducer.py
# Reducers for use by ISIS Molecular Spectroscopy Group
import os.path
from mantid.simpleapi import *
from mantid.kernel import config
import reduction.reducer as reducer
import inelastic_indirect_reduction_steps as steps
class MSGReducer(reducer.Reducer):
"""This is the base class for the reducer classes to be used by the ISIS
Molecular Spectroscopy Group (MSG). It exists to serve the functions that
are common to both spectroscopy and diffraction workflows in the hopes of
providing a semi-consistent interface to both.
"""
_instrument_name = None #: Name of the instrument used in experiment.
_sum = False #: Whether to sum input files or treat them sequentially.
_load_logs = False #: Whether to load the log file(s) associated with the raw file.
_monitor_index = None #: Index of Monitor specturm.
_multiple_frames = False
_detector_range = [-1, -1]
_masking_detectors = []
_parameter_file = None
_rebin_string = None
_fold_multiple_frames = True
_save_formats = []
_info_table_props = None
_extra_load_opts = {}
def __init__(self):
super(MSGReducer, self).__init__()
def pre_process(self):
self._reduction_steps = []
loadData = steps.LoadData()
loadData.set_ws_list(self._data_files)
loadData.set_sum(self._sum)
loadData.set_load_logs(self._load_logs)
loadData.set_monitor_index(self._monitor_index)
loadData.set_detector_range(self._detector_range[0],
self._detector_range[1])
loadData.set_parameter_file(self._parameter_file)
loadData.set_extra_load_opts(self._extra_load_opts)
loadData.execute(self, None)
self._multiple_frames = loadData.is_multiple_frames()
self._masking_detectors = loadData.get_mask_list()
if( self._info_table_props is not None ):
wsNames = loadData.get_ws_list().keys()
wsNameList = ", ".join(wsNames)
propsList = ", ".join(self._info_table_props)
CreateLogPropertyTable(
OutputWorkspace="RunInfo",
InputWorkspaces=wsNameList,
LogPropertyNames=propsList,
GroupPolicy="First")
if ( self._sum ):
self._data_files = loadData.get_ws_list()
self._setup_steps()
def set_detector_range(self, start, end):
"""Sets the start and end detector points for the reduction process.
These numbers are to be the *workspace index*, not the spectrum number.
Example:
reducer.set_detector_range(2,52)
"""
if ( not isinstance(start, int) ) or ( not isinstance(end, int) ):
raise TypeError("start and end must be integer values")
self._detector_range = [ start, end ]
def set_fold_multiple_frames(self, value):
"""When this is set to False, the reducer will not run the FoldData
reduction step or any step which appears after it in the reduction
chain.
This will only affect data which would ordinarily have used this
function (ie TOSCA on multiple frames).
"""
if not isinstance(value, bool):
raise TypeError("value must be of boolean type")
self._fold_multiple_frames = value
def set_instrument_name(self, instrument):
"""Unlike the SANS reducers, we do not create a class to describe the
instruments. Instead, we load the instrument and parameter file and
query it for information.
Raises:
* ValueError if an instrument name is not provided.
* RuntimeError if IDF could not be found or is invalid.
* RuntimeError if workspace index of the Monitor could not be
determined.
Example use:
reducer.set_instrument_name("IRIS")
"""
if not isinstance(instrument, str):
raise ValueError("Instrument name must be given.")
self._instrument_name = instrument
self._load_empty_instrument()
self._get_monitor_index()
if ( self._monitor_index is None ):
raise RuntimeError("Could not find Monitor in Instrument.")
def set_parameter_file(self, file):
"""Sets the parameter file to be used in the reduction. The parameter
file will contain some settings that are used throughout the reduction
process.
Note: This is *not* the base parameter file, ie "IRIS_Parameters.xml"
but, rather, the additional parameter file.
"""
if self._instrument_name is None:
raise ValueError("Instrument name not set.")
self._parameter_file = \
os.path.join(config["parameterDefinition.directory"], file)
LoadParameterFile(Workspace=self._workspace_instrument,Filename=
self._parameter_file)
def set_rebin_string(self, rebin):
"""Sets the rebin string to be used with the Rebin algorithm.
"""
if not isinstance(rebin, str):
raise TypeError("rebin variable must be of string type")
self._rebin_string = rebin
def set_sum_files(self, value):
"""Mark whether multiple runs should be summed together for the process
or treated individually.
The default value for this is False.
"""
if not isinstance(value, bool):
raise TypeError("value must be either True or False (boolean)")
self._sum = value
def set_load_logs(self, value):
"""Mark whether the log file(s) associated with a raw file should be
loaded along with the raw file.
The default value for this is False.
"""
if not isinstance(value, bool):
raise TypeError("value must be either True or False (boolean)")
self._load_logs = value
def set_save_formats(self, formats):
"""Selects the save formats in which to export the reduced data.
formats should be a list object of strings containing the file
extension that signifies the type.
For example:
reducer.set_save_formats(['nxs', 'spe'])
Tells the reducer to save the final result as a NeXuS file, and as an
SPE file.
Please see the documentation for the SaveItem reduction step for more
details.
"""
if not isinstance(formats, list):
raise TypeError("formats variable must be of list type")
self._save_formats = formats
def append_load_option(self, name, value):
"""
Additional options for the Load call, require name & value
of property
"""
self._extra_load_opts[name] = value
def get_result_workspaces(self):
"""Returns a Python list object containing the names of the workspaces
processed at the last reduction step. Using this, you can incorporate
the reducer into your own scripts.
It will only be effective after the reduce() function has run.
Example:
wslist = reducer.get_result_workspaces()
plotSpectrum(wslist, 0) # Plot the first spectrum of each of
# the result workspaces
"""
nsteps = len(self._reduction_steps)
for i in range(0, nsteps):
try:
step = self._reduction_steps[nsteps-(i+1)]
return step.get_result_workspaces()
except AttributeError:
pass
except IndexError:
raise RuntimeError("None of the reduction steps implement "
"the get_result_workspaces() method.")
def _load_empty_instrument(self):
"""Returns an empty workspace for the instrument.
Raises:
* ValueError if no instrument is selected.
* RuntimeError if there is a problem with the IDF.
"""
if self._instrument_name is None:
raise ValueError('No instrument selected.')
self._workspace_instrument = '__empty_' + self._instrument_name
if not mtd.doesExist(self._workspace_instrument):
idf_dir = config.getString('instrumentDefinition.directory')
idf = idf_dir + self._instrument_name + '_Definition.xml'
try:
LoadEmptyInstrument(Filename=idf,OutputWorkspace= self._workspace_instrument)
except RuntimeError:
raise ValueError('Invalid IDF')
return mtd[self._workspace_instrument]
def _get_monitor_index(self):
"""Determine the workspace index of the first monitor spectrum.
"""
workspace = self._load_empty_instrument()
for counter in range(0, workspace.getNumberHistograms()):
try:
detector = workspace.getDetector(counter)
except RuntimeError:
pass
if detector.isMonitor():
self._monitor_index = counter
return