forked from AmbaPant/mantid
-
Notifications
You must be signed in to change notification settings - Fork 1
/
MaskAngle.py
131 lines (111 loc) · 5.39 KB
/
MaskAngle.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
# 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
import mantid.simpleapi
import mantid.kernel
import mantid.api
import mantid.geometry
import numpy
class MaskAngle(mantid.api.PythonAlgorithm):
""" Mask detectors between specified angles based on angle type required
"""
def category(self):
""" Mantid required
"""
return "Transforms\\Masking"
def seeAlso(self):
return [ "MaskDetectors" ]
def name(self):
""" Mantid require
"""
return "MaskAngle"
def summary(self):
""" Mantid require
"""
return "Algorithm to mask detectors with scattering angles in a given interval (in degrees)."
def PyInit(self):
self.declareProperty(mantid.api.WorkspaceProperty("Workspace", "",direction=mantid.kernel.Direction.Input),
"Input workspace")
angleValidator=mantid.kernel.FloatBoundedValidator()
angleValidator.setBounds(-180.,180.)
self.declareProperty(name="MinAngle", defaultValue=0.0, validator=angleValidator,
direction=mantid.kernel.Direction.Input, doc="Angles above MinAngle are going to be masked")
self.declareProperty(name="MaxAngle", defaultValue=180.0, validator=angleValidator,
direction=mantid.kernel.Direction.Input, doc="Angles below MaxAngle are going to be masked")
self.declareProperty('Angle', 'TwoTheta',
mantid.kernel.StringListValidator(['TwoTheta', 'Phi', 'InPlane']),
'Which angle to use')
self.declareProperty(mantid.kernel.IntArrayProperty(name="MaskedDetectors", direction=mantid.kernel.Direction.Output),
doc="List of detector masked, with scattering angles between MinAngle and MaxAngle")
def validateInputs(self):
issues = dict()
ws = self.getProperty("Workspace").value
hasInstrument = True
if type(ws).__name__ == "WorkspaceGroup" and len(ws) > 0:
for item in ws:
hasInstrument = hasInstrument and len(item.componentInfo()) > 0
else:
hasInstrument = len(ws.componentInfo()) > 0
if not hasInstrument:
issues["Workspace"] = "Workspace must have an associated instrument."
angleMin = self.getProperty('MinAngle').value
angleMax = self.getProperty('MaxAngle').value
if angleMin >= angleMax:
msg = 'MinAngle ({}) must be less than MaxAngle ({})'.format(angleMin, angleMax)
issues['MinAngle'] = msg
issues['MaxAngle'] = msg
if self.getProperty('Angle').value != 'InPlane':
if angleMin < 0.:
issues['MinAngle'] = 'Must be positive'
if angleMax < 0.:
issues['MaxAngle'] = 'Must be positive'
return issues
def _get_phi(self, spectra_pos):
'''
The implementation here assumes that z is the beam direction.
That assumption is not universally true, it depends on the geometry configuration.
This returns the phi spherical coordinate value
'''
return numpy.fabs(numpy.arctan2(spectra_pos.Y(), spectra_pos.X()))
def _get_in_plane(self, spectra_pos):
'''
The implementation here assumes that z is the beam direction and x is in plane.
That assumption is not universally true, it depends on the geometry configuration.
This returns the angle from the z-axis constrained in-plane
'''
return numpy.arctan2(spectra_pos.X(), spectra_pos.Z())
def PyExec(self):
ws = self.getProperty("Workspace").value
ttmin = numpy.radians(self.getProperty("MinAngle").value)
ttmax = numpy.radians(self.getProperty("MaxAngle").value)
if ttmin > ttmax :
raise ValueError("MinAngle > MaxAngle, please check angle range for masking")
angle_phi = self.getProperty('Angle').value == 'Phi'
angle_in_plane = self.getProperty('Angle').value == 'InPlane'
spectrum_info = ws.spectrumInfo()
detector_info = ws.detectorInfo()
det_ids = detector_info.detectorIDs()
masked_ids = list()
for spectrum in spectrum_info:
if not spectrum.isMonitor:
# Get the first detector of spectrum. Ignore time aspects.
if angle_phi:
val = self._get_phi(spectrum.position)
elif angle_in_plane:
val = self._get_in_plane(spectrum.position)
else: # Two theta
val =spectrum.twoTheta
if val>= ttmin and val<= ttmax:
detectors = spectrum.spectrumDefinition
for j in range(len(detectors)):
masked_ids.append(det_ids[detectors[j][0]])
if not masked_ids:
self.log().information("no detectors within this range")
else:
mantid.simpleapi.MaskDetectors(Workspace=ws,DetectorList=numpy.array(masked_ids))
self.setProperty("MaskedDetectors", numpy.array(masked_ids))
mantid.api.AlgorithmFactory.subscribe(MaskAngle)