forked from AmbaPant/mantid
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ExportGeometry.py
151 lines (121 loc) · 5.62 KB
/
ExportGeometry.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
# 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
from mantid.api import PythonAlgorithm, AlgorithmFactory, WorkspaceProperty, \
InstrumentValidator, FileProperty, FileAction
from mantid.kernel import Direction, StringArrayProperty, StringListValidator
SOURCE_XML = """ <!--SOURCE-->
<component type="moderator">
<location z="%(z)f"/>
</component>
<type is="Source" name="moderator"/>
"""
SAMPLE_XML = """ <!--SAMPLE-->
<component type="sample-position">
<location x="%(x)f" y="%(y)f" z="%(z)f"/>
</component>
<type is="SamplePos" name="sample-position"/>
"""
COMPONENT_XML_FULL = """ <location x="%(x)f" y="%(y)f" z="%(z)f" name="%(name)s">
<rot %(alpha_string)s">
<rot %(beta_string)s">
<rot %(gamma_string)s"/>
</rot>
</rot>
</location>
"""
# no rotation needs to be specified
COMPONENT_XML_MINIMAL = """ <location x="%(x)f" y="%(y)f" z="%(z)f" name="%(name)s">
</location>
"""
class ExportGeometry(PythonAlgorithm):
_eulerCon = None
_eulerXML={"X":'axis-x="1" axis-y="0" axis-z="0" val="',
"Y":'axis-x="0" axis-y="1" axis-z="0" val="',
"Z":'axis-x="0" axis-y="0" axis-z="1" val="'}
def category(self):
return "Utility\\Instrument"
def seeAlso(self):
return [ "LoadInstrument" ]
def name(self):
return "ExportGeometry"
def summary(self):
return "Extract components from larger in-memory instrument, save as IDF style xml"
def PyInit(self):
self.declareProperty(WorkspaceProperty("InputWorkspace", "",
validator=InstrumentValidator(),
direction=Direction.Input),
doc="Workspace containing the instrument to be exported")
eulerConventions = ["ZXZ", "XYX", "YZY", "ZYZ", "XZX", "YXY",
"XYZ", "YZX", "ZXY", "XZY", "ZYX", "YXZ"]
self.declareProperty(name="EulerConvention", defaultValue="YZY",
validator=StringListValidator(eulerConventions),
doc="Euler angles convention used when writing angles.")
self.declareProperty(StringArrayProperty("Components",
direction=Direction.Input),
doc="Comma separated list of instrument component names to export")
self.declareProperty(FileProperty(name="Filename",
defaultValue="",
action=FileAction.Save,
extensions=[".xml"]),
doc="Save file")
def validateInputs(self):
issues = {}
# get the input workspace
wksp = self.getProperty("InputWorkspace").value
# confirm that all of the requested components exist
components = self.getProperty("Components").value
if len(components) <= 0:
issues['Components'] = "Must supply components"
else:
components = [component for component in components
if wksp.getInstrument().getComponentByName(component) is None]
if len(components) > 0:
issues['Components'] = "Instrument has no component \"" \
+ ','.join(components) + "\""
return issues
def __updatePos(self, info, component):
pos = component.getPos()
info['x'] = pos.X()
info['y'] = pos.Y()
info['z'] = pos.Z()
angles = component.getRotation().getEulerAngles(self._eulerCon)
info['alpha'] = angles[0]
info['beta'] = angles[1]
info['gamma'] = angles[2]
info['alpha_string'] = self._eulerXML[self._eulerCon[0]] + str(angles[0])
info['beta_string'] = self._eulerXML[self._eulerCon[1]] + str(angles[1])
info['gamma_string'] = self._eulerXML[self._eulerCon[2]] + str(angles[2])
def __writexmlSource(self, handle, instrument):
source = {}
self.__updatePos(source, instrument.getSource())
handle.write(SOURCE_XML % source)
sample = {}
self.__updatePos(sample, instrument.getSample())
handle.write(SAMPLE_XML % sample)
def __writexml(self, handle, component):
info = {'name': component.getName()}
self.__updatePos(info, component)
if info['alpha'] == 0. and info['beta'] == 0. and info['gamma'] == 0.:
handle.write(COMPONENT_XML_MINIMAL % info)
else:
handle.write(COMPONENT_XML_FULL % info)
def PyExec(self):
wksp = self.getProperty("InputWorkspace").value
components = self.getProperty("Components").value
filename = self.getProperty("Filename").value
self._eulerCon = self.getProperty("EulerConvention").value
instrument = wksp.getInstrument()
with open(filename, 'w') as handle:
# write out the source and sample components
self.__writexmlSource(handle, instrument)
# write out the requested components
handle.write(""" <!--COMPONENTS-->\n""")
for component in components:
component = instrument.getComponentByName(component)
self.__writexml(handle, component)
AlgorithmFactory.subscribe(ExportGeometry)