-
Notifications
You must be signed in to change notification settings - Fork 121
/
PDConvertReciprocalSpace.py
133 lines (114 loc) · 4.96 KB
/
PDConvertReciprocalSpace.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
# 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,invalid-name
from mantid.api import (
PythonAlgorithm,
AlgorithmFactory,
WorkspaceUnitValidator,
MatrixWorkspaceProperty,
WorkspaceProperty,
WorkspaceFactory,
)
from mantid.kernel import Direction, StringListValidator, logger
from pystog.converter import Converter
SQ = "S(Q)"
FQ = "F(Q)"
FKQ = "FK(Q)"
DCS = "DCS(Q)"
class PDConvertReciprocalSpace(PythonAlgorithm):
"""
Convert between different reciprocal space functions
"""
def category(self):
"""
Return category
"""
return "Diffraction\\Utility"
def name(self):
"""
Return name
"""
return "PDConvertReciprocalSpace"
def seeAlso(self):
return ["PDConvertRealSpace"]
def summary(self):
return "Transforms a Workspace2D between different " + "reciprocal space functions."
def PyInit(self):
"""
Declare properties
"""
allowed_units = WorkspaceUnitValidator("MomentumTransfer")
self.declareProperty(
MatrixWorkspaceProperty("InputWorkspace", "", direction=Direction.Input, validator=allowed_units),
doc="Input workspace with units of momentum transfer",
)
functions = [SQ, FQ, FKQ, DCS]
self.declareProperty("From", SQ, StringListValidator(functions), "Function type in the input workspace")
self.declareProperty("To", SQ, StringListValidator(functions), "Function type in the output workspace")
self.declareProperty(WorkspaceProperty("OutputWorkspace", "", direction=Direction.Output), doc="Output workspace")
def validateInputs(self):
result = dict()
input_ws = self.getProperty("InputWorkspace").value
from_quantity = self.getProperty("From").value
to_quantity = self.getProperty("To").value
if from_quantity != to_quantity: # noop doesn't require material
requireMaterial = True
if from_quantity == SQ and to_quantity == FQ:
requireMaterial = False
elif from_quantity == FQ and to_quantity == SQ:
requireMaterial = False
if requireMaterial:
if not input_ws.sample().getMaterial():
result["InputWorkspace"] = "Please run SetSample or SetSampleMaterial"
else:
cohScattSqrd = input_ws.sample().getMaterial().cohScatterLengthSqrd()
if cohScattSqrd == 0.0:
if from_quantity in [SQ, FQ] and to_quantity in [DCS, FKQ]:
result["To"] = "Require non-zero coherent scattering length"
if to_quantity in [SQ, FQ] and from_quantity in [DCS, FKQ]:
result["From"] = "Require non-zero coherent scattering length"
return result
def PyExec(self):
input_ws = self.getProperty("InputWorkspace").value
output_ws_name = self.getProperty("OutputWorkspace").valueAsStr
from_quantity = self.getProperty("From").value
to_quantity = self.getProperty("To").value
if input_ws.name() == output_ws_name:
output_ws = input_ws
else:
output_ws = WorkspaceFactory.create(input_ws)
self.setProperty("OutputWorkspace", output_ws)
if from_quantity == to_quantity:
logger.warning("The input and output functions are the same. Nothing to be done")
return
c = Converter()
transformation = {
SQ: {FQ: c.S_to_F, FKQ: c.S_to_FK, DCS: c.S_to_DCS},
FQ: {SQ: c.F_to_S, FKQ: c.F_to_FK, DCS: c.F_to_DCS},
FKQ: {SQ: c.FK_to_S, FQ: c.FK_to_F, DCS: c.FK_to_DCS},
DCS: {SQ: c.DCS_to_S, FQ: c.DCS_to_F, FKQ: c.DCS_to_FK},
}
if input_ws.sample().getMaterial():
sample_kwargs = {
"<b_coh>^2": input_ws.sample().getMaterial().cohScatterLengthSqrd(),
"<b_tot^2>": input_ws.sample().getMaterial().totalScatterLengthSqrd(),
"rho": input_ws.sample().getMaterial().numberDensity,
}
else:
sample_kwargs = dict()
for sp_num in range(input_ws.getNumberHistograms()):
x = input_ws.readX(sp_num)
output_ws.setX(sp_num, x)
y = input_ws.readY(sp_num)
e = input_ws.readE(sp_num)
if len(x) == len(y) + 1:
x = 0.5 * (x[:-1] + x[1:])
new_y, new_e = transformation[from_quantity][to_quantity](x, y, e, **sample_kwargs)
output_ws.setY(sp_num, new_y)
output_ws.setE(sp_num, new_e)
# Register algorithm with Mantid.
AlgorithmFactory.subscribe(PDConvertReciprocalSpace)