forked from AmbaPant/mantid
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMRGetTheta.py
103 lines (86 loc) · 4.59 KB
/
MRGetTheta.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
# 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, WorkspaceProperty
from mantid.kernel import Direction, FloatBoundedValidator, Property
import mantid.simpleapi
import math
class MRGetTheta(PythonAlgorithm):
""" Get the theta scattering angle for the Magnetism Reflectometer """
def category(self):
""" Return category """
return "Reflectometry\\SNS"
def name(self):
""" Return name """
return "MRGetTheta"
def summary(self):
""" Return summary """
return "Get the theta scattering angle for the Magnetism Reflectometer (radians)."
def PyInit(self):
""" Declare properties """
self.declareProperty(WorkspaceProperty("Workspace", "", Direction.Input), "Workspace containing MR data")
self.declareProperty("AngleOffset", 0.,FloatBoundedValidator(lower=0.), "Angle offset (rad)")
self.declareProperty("UseSANGLE", False, doc="If True, use SANGLE as the scattering angle. If False, use DANGLE.")
self.declareProperty("SpecularPixel", 0., doc="Pixel position of the specular reflectivity [optional]")
self.declareProperty("DirectPixelOverwrite", Property.EMPTY_DBL, doc="DIRPIX overwrite value")
self.declareProperty("DAngle0Overwrite", Property.EMPTY_DBL, doc="DANGLE0 overwrite value (degrees)")
self.declareProperty("Theta", 0., direction=Direction.Output, doc="Scattering angle theta (rad)")
return
def PyExec(self):
""" Main execution body """
_w=self.getProperty("Workspace").value
angle_offset = self.getProperty("AngleOffset").value
dirpix_overwrite = self.getProperty("DirectPixelOverwrite").value
dangle0_overwrite = self.getProperty("DAngle0Overwrite").value
use_sangle = self.getProperty("UseSANGLE").value
if use_sangle:
theta = self.read_log(_w, 'SANGLE', target_units='rad', assumed_units='deg')
else:
dangle = self.read_log(_w, 'DANGLE', target_units='rad', assumed_units='deg')
if dangle0_overwrite == Property.EMPTY_DBL:
dangle0 = self.read_log(_w, 'DANGLE0', target_units='rad', assumed_units='deg')
else:
dangle0 = dangle0_overwrite * math.pi / 180.0
det_distance = self.read_log(_w, 'SampleDetDis', target_units='m', assumed_units='mm')
if dirpix_overwrite == Property.EMPTY_DBL:
direct_beam_pix = _w.getRun()['DIRPIX'].getStatistics().mean
else:
direct_beam_pix = dirpix_overwrite
ref_pix = self.getProperty("SpecularPixel").value
if ref_pix == 0.:
ref_pix = direct_beam_pix
# Get pixel size from instrument properties
if _w.getInstrument().hasParameter("pixel-width"):
pixel_width = float(_w.getInstrument().getNumberParameter("pixel-width")[0]) / 1000.0
else:
mantid.simpleapi.logger.warning("Not pixel width found in instrument, assuming 0.7 mm.")
pixel_width = 0.0007
theta = (dangle - dangle0) / 2.0 + ((direct_beam_pix - ref_pix) * pixel_width) / (2.0 * det_distance)
self.setProperty("Theta", abs(theta) + angle_offset)
return
def read_log(self, ws, name, target_units='', assumed_units=''):
"""
Read a log value, taking care of units.
If the log entry has no units, the target units are assumed.
:param ws: workspace
:param str name: name of the property to read
:param str target_units: units to convert to
:param str assumed_units: units of origin, if not specified in the log itself
"""
_units = {'m': {'mm': 1000.0,},
'mm': {'m': 0.001,},
'deg': {'rad': math.pi/180.,},
'rad': {'deg': 180./math.pi,},
}
prop = ws.getRun().getProperty(name)
value = prop.getStatistics().mean
# If the property has units we don't recognize, use the assumed units
units = prop.units if prop.units in _units else assumed_units
if units in _units and target_units in _units[units]:
return value * _units[units][target_units]
return value
AlgorithmFactory.subscribe(MRGetTheta)