Newer
Older
from __future__ import (absolute_import, division, print_function)
import math
import os
import re
from collections import defaultdict
from string import Formatter
from mantid.api import *
from mantid.kernel import *
class SaveGEMMAUDParamFile(PythonAlgorithm):
PROP_INPUT_WS = "InputWorkspace"
PROP_TEMPLATE_FILE = "TemplateFilename"
PROP_GROUPING_SCHEME = "GroupingScheme"
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
PROP_GSAS_PARAM_FILE = "GSASParamFile"
PROP_OUTPUT_FILE = "OutputFilename"
BANK_PARAMS_LINE = "^INS [0-9]BNKPAR"
DIFFRACTOMETER_CONSTANTS_LINE = "^INS [0-9] ICONS"
PROFILE_COEFFS_LINE_1 = "^INS [0-9]PRCF 1"
PROFILE_COEFFS_LINE_2 = "^INS [0-9]PRCF 2"
def category(self):
return "DataHandling\\Text;Diffraction\\DataHandling"
def name(self):
return "SaveGEMMAUDParamFile"
def summary(self):
return "Read calibration information from focused workspace and GSAS parameter file, and save to " \
"MAUD-readable calibration format"
def PyInit(self):
self.declareProperty(WorkspaceGroupProperty(name=self.PROP_INPUT_WS,
defaultValue="",
direction=Direction.Input),
doc="WorkspaceGroup of focused banks")
self.declareProperty(FileProperty(name=self.PROP_GSAS_PARAM_FILE,
action=FileAction.Load,
defaultValue=""),
doc="GSAS parameter file to read diffractometer constants and profile coefficients from")
self.declareProperty(FileProperty(name=self.PROP_TEMPLATE_FILE,
action=FileAction.Load,
defaultValue=self._find_isis_powder_dir()),
doc="Template for the .maud file")
self.declareProperty(IntArrayProperty(name=self.PROP_GROUPING_SCHEME),
doc="An array of bank IDs, where the value at element i is the ID of the bank in " +
self.PROP_GSAS_PARAM_FILE + " to associate spectrum i with")
self.declareProperty(FileProperty(name=self.PROP_OUTPUT_FILE,
action=FileAction.Save,
defaultValue=""),
doc="Name of the file to save to")
def PyExec(self):
input_ws = mtd[self.getPropertyValue(self.PROP_INPUT_WS)]
gsas_filename = self.getProperty(self.PROP_GSAS_PARAM_FILE).value
num_banks = input_ws.getNumberOfEntries()
grouping_scheme = self.getProperty(self.PROP_GROUPING_SCHEME).value
# closure around self._expand_to_texture_bank, capturing num_banks and grouping_scheme
def expand_to_texture_bank(bank_param_list):
return self._expand_to_texture_bank(bank_param_list=bank_param_list,
spectrum_numbers=range(num_banks),
grouping_scheme=grouping_scheme)
output_params = {}
gsas_file_params = self._parse_gsas_param_file(gsas_filename)
gsas_file_params_to_write = {key: self._format_param_list(expand_to_texture_bank(gsas_file_params[key]))
for key in gsas_file_params}
output_params.update(gsas_file_params_to_write)
two_thetas, phis = zip(*[self._get_two_theta_and_phi(bank) for bank in input_ws])
output_params["thetas"] = self._format_param_list(two_thetas)
output_params["etas"] = self._format_param_list(phis)
def create_empty_param_list(default_value="0"):
return "\n".join(default_value for _ in range(num_banks))
with open(self.getProperty(self.PROP_TEMPLATE_FILE).value) as template_file:
template = template_file.read()
output_params["function_types"] = create_empty_param_list("1")
output_params["gsas_prm_file"] = gsas_filename
output_params["inst_counter_bank"] = "Bank1"
output_params["bank_ids"] = "\n".join("Bank{}".format(i + 1) for i in range(num_banks))
with open(self.getProperty(self.PROP_OUTPUT_FILE).value, "w") as output_file:
# Note, once we've got rid of Python 2 support this can be simplified to
# template.format_map(defaultdict(create_empty_param_list, output_params))
output_file.write(Formatter().vformat(template, (),
defaultdict(create_empty_param_list,
output_params)))
def validateInputs(self):
issues = {}
input_ws = mtd[self.getPropertyValue(self.PROP_INPUT_WS)]
grouping_scheme = self.getProperty(self.PROP_GROUPING_SCHEME).value
if len(grouping_scheme) != input_ws.getNumberOfEntries():
issues[self.PROP_GROUPING_SCHEME] = ("Number of entries in {} does not match number of spectra in {}. "
"You must assign a bank to every focused spectrum in the input workspace".
format(self.PROP_GROUPING_SCHEME, self.PROP_INPUT_WS))
return issues
def _expand_to_texture_bank(self, bank_param_list, spectrum_numbers, grouping_scheme):
"""
:param bank_param_list: a list of n values for some parameter, such as DIFC
:param spectrum_numbers: a list of m bank IDs, one for each focused spectrum
:param grouping_scheme: a list of m indexes, to index bank_param_list, where
the element at item i is the bank number in bank_param_list to associate
focused spectrum i with
:return: a list of m values, where each value is the assigned parameter for the
corresponding bank
"""
return (bank_param_list[grouping_scheme[spec_num] - 1] for spec_num in spectrum_numbers)
script_dirs = [directory for directory in config["pythonscripts.directories"].split(";")
if "Diffraction" in directory]
for directory in script_dirs:
path_to_test = os.path.join(directory,
"isis_powder",
"gem_routines",
"maud_param_template.maud")
if os.path.exists(path_to_test):
return path_to_test
logger.warning("Could not find default diffraction directory for .maud template file: "
"you'll have to find it yourself")
return ""
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
def _format_param_list(self, param_list):
return "\n".join(str(param) for param in param_list)
def _get_two_theta_and_phi(self, bank):
instrument = bank.getInstrument()
detector = bank.getDetector(0)
sample_pos = instrument.getSample().getPos()
source_pos = instrument.getSource().getPos()
det_pos = detector.getPos()
beam_dir = sample_pos - source_pos
detector_dir = det_pos - sample_pos
return math.degrees(beam_dir.angle(detector_dir)), math.degrees(detector.getPhi())
def _parse_gsas_param_file(self, gsas_filename):
with open(gsas_filename) as prm_file:
gsas_params_lines = prm_file.read().split("\n")
distances = []
difcs = []
difas = []
tzeros = []
alpha_zeros = []
alpha_ones = []
beta_zeros = []
beta_ones = []
sigma_zeros = []
sigma_ones = []
sigma_twos = []
for line in gsas_params_lines:
line_items = line.split()
if re.match(self.BANK_PARAMS_LINE, line):
distances.append(float(line_items[2]))
elif re.match(self.DIFFRACTOMETER_CONSTANTS_LINE, line):
difcs.append(float(line_items[3]))
difas.append(float(line_items[4]))
tzeros.append(float(line_items[5]))
elif re.match(self.PROFILE_COEFFS_LINE_1, line):
alpha_zeros.append(float(line_items[3]))
alpha_ones.append(float(line_items[4]))
beta_zeros.append(float(line_items[5]))
beta_ones.append(float(line_items[6]))
elif re.match(self.PROFILE_COEFFS_LINE_2, line):
sigma_zeros.append(float(line_items[3]))
sigma_ones.append(float(line_items[4]))
sigma_twos.append(float(line_items[5]))
return {"dists": distances,
"difas": difas,
"difcs": difcs,
"tzeros": tzeros,
"func_1_alpha_zeros": alpha_zeros,
"func_1_alpha_ones": alpha_ones,
"func_1_beta_zeros": beta_zeros,
"func_1_beta_ones": beta_ones,
"func_1_sigma_zeros": sigma_zeros,
"func_1_sigma_ones": sigma_ones,
"func_1_sigma_twos": sigma_twos}
AlgorithmFactory.subscribe(SaveGEMMAUDParamFile)