Mantid
Loading...
Searching...
No Matches
ComponentInfo.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8#include "MantidBeamline/ComponentType.h"
9#include "MantidBeamline/PixelGridComponent.h"
13#include "MantidKernel/Quat.h"
14#include "MantidKernel/V3D.h"
17#include "MantidPythonInterface/geometry/ComponentInfoPythonIterator.h"
18
19#include <boost/python/class.hpp>
20#include <boost/python/copy_const_reference.hpp>
21#include <boost/python/dict.hpp>
22#include <boost/python/enum.hpp>
23#include <boost/python/reference_existing_object.hpp>
24#include <boost/python/return_value_policy.hpp>
25
26using Mantid::Beamline::ComponentType;
27using Mantid::Beamline::PixelGridComponent;
32using Mantid::PythonInterface::ComponentInfoPythonIterator;
35using namespace boost::python;
36
37namespace {
38ComponentInfoPythonIterator make_pyiterator(ComponentInfo &componentInfo) {
39 return ComponentInfoPythonIterator(componentInfo);
40}
41
42// Accept a bare observer position so this reads as a drop-in for the legacy
43// IDetector::solidAngle(observer), constructing SolidAngleParams internally.
44double solidAngle(const ComponentInfo &self, const size_t index, const V3D &observer) {
45 return self.solidAngle(index, SolidAngleParams(observer));
46}
47
48// Flat accessors for the grid metadata of a Rectangular/Grid bank. The
49// Beamline::PixelGridComponent aggregate is an implementation detail of the
50// Geometry layer and is deliberately not exported to Python; one member is
51// fetched per call.
52template <auto Field> auto pixelGridField(ComponentInfo const &self, size_t const componentIndex) {
53 return self.pixelGridComponent(componentIndex).*Field;
54}
55
56// Axis fill order ('x'/'y'/'z' permutation) as a 3-character string, since
57// std::array<char, 3> has no automatic boost::python converter.
58std::string pixelGridIdFillOrder(ComponentInfo const &self, size_t const componentIndex) {
59 auto const order = self.pixelGridComponent(componentIndex).idFillOrder;
60 return std::string(order.begin(), order.end());
61}
62
63dict shapeToComponentIndices(const ComponentInfo &componentInfo) {
64 dict result;
65 const auto shapeMap = componentInfo.shapeToComponentIndices();
66 for (const auto &shape : shapeMap) {
67 const auto csgObject = std::dynamic_pointer_cast<const Mantid::Geometry::CSGObject>(shape.first);
68 if (csgObject != nullptr) {
69 result[csgObject->getShapeXML()] = shape.second;
70 }
71 }
72 return result;
73}
74
75} // namespace
76
77// Function pointers to help resolve ambiguity
79
81
82void (ComponentInfo::*setPosition)(const size_t, const Mantid::Kernel::V3D &) = &ComponentInfo::setPosition;
83
84void (ComponentInfo::*setRotation)(const size_t, const Mantid::Kernel::Quat &) = &ComponentInfo::setRotation;
85
86// Export ComponentInfo
88 enum_<ComponentType>("ComponentType")
89 .value("Generic", ComponentType::Generic)
90 .value("Infinite", ComponentType::Infinite)
91 .value("Grid", ComponentType::Grid)
92 .value("Rectangular", ComponentType::Rectangular)
93 .value("Structured", ComponentType::Structured)
94 .value("Unstructured", ComponentType::Unstructured)
95 .value("Detector", ComponentType::Detector)
96 .value("OutlineComposite", ComponentType::OutlineComposite);
97
98 class_<ComponentInfo, boost::noncopyable>("ComponentInfo", no_init)
99
100 .def("__iter__", make_pyiterator)
101
102 .def("__len__", &ComponentInfo::size, arg("self"), "Returns the number of components.")
103
104 .def("size", &ComponentInfo::size, arg("self"), "Returns the number of components.")
105
106 .def("isDetector", &ComponentInfo::isDetector, (arg("self"), arg("index")),
107 "Checks if the component is a detector.")
108
109 .def("detectorsInSubtree", &ComponentInfo::detectorsInSubtree, return_value_policy<VectorToNumpy>(),
110 (arg("self"), arg("index")),
111 "Returns a list of detectors in the subtree for the component "
112 "identified by 'index'.")
113
114 .def("componentsInSubtree", &ComponentInfo::componentsInSubtree, return_value_policy<VectorToNumpy>(),
115 (arg("self"), arg("index")),
116 "Returns a list of components in the subtree for the component "
117 "identified by 'index'.")
118
119 .def("position", position, (arg("self"), arg("index")),
120 "Returns the absolute position of the component identified by "
121 "'index'.")
122
123 .def("rotation", rotation, (arg("self"), arg("index")),
124 "Returns the absolute rotation of the component identified by "
125 "'index'.")
126
127 .def("relativePosition", &ComponentInfo::relativePosition, (arg("self"), arg("index")),
128 "Returns the absolute relative position of the component identified "
129 "by 'index'.")
130
131 .def("relativeRotation", &ComponentInfo::relativeRotation, (arg("self"), arg("index")),
132 "Returns the absolute relative rotation of the component identified "
133 "by 'index'.")
134
135 .def("setPosition", setPosition, (arg("self"), arg("index"), arg("newPosition")),
136 "Set the absolute position of the component identified by 'index'.")
137
138 .def("setRotation", setRotation, (arg("self"), arg("index"), arg("newRotation")),
139 "Set the absolute rotation of the component identified by 'index'.")
140
141 .def("hasSource", &ComponentInfo::hasSource, arg("self"), "Returns True if a source is present.")
142
143 .def("hasEquivalentSource", &ComponentInfo::hasEquivalentSource, arg("self"), arg("other"),
144 "Returns True is both beamlines either lack a Source or "
145 "have a Source at the same position.")
146
147 .def("hasSample", &ComponentInfo::hasSample, arg("self"), "Returns True if a sample is present.")
148
149 .def("hasEquivalentSample", &ComponentInfo::hasEquivalentSample, arg("self"), arg("other"),
150 "Returns True is both beamlines either lack a Sample or "
151 "have a Sample at the same position.")
152
153 .def("source", &ComponentInfo::source, arg("self"), "Returns the source component index.")
154
155 .def("sample", &ComponentInfo::sample, arg("self"), "Returns the sample component index.")
156
157 .def("sourcePosition", &ComponentInfo::sourcePosition, arg("self"), "Returns the source position.")
158
159 .def("samplePosition", &ComponentInfo::samplePosition, arg("self"), "Returns the sample position.")
160
161 .def("hasParent", &ComponentInfo::hasParent, (arg("self"), arg("index")),
162 "Returns True only if the component identified by 'index' has a "
163 "parent component.")
164
165 .def("parent", &ComponentInfo::parent, (arg("self"), arg("index")),
166 "Returns the parent component of the component identified by "
167 "'index'.")
168
169 .def("children", &ComponentInfo::children, (arg("self"), arg("index")),
170 return_value_policy<VectorRefToNumpy<WrapReadOnly>>(),
171 "Returns a list of child components for the component identified by "
172 "'index'.")
173
174 .def("name", &ComponentInfo::name, (arg("self"), arg("index")), return_value_policy<copy_const_reference>(),
175 "Returns the name of the component identified by 'index'.")
176
177 .def("l1", &ComponentInfo::l1, arg("self"), "Returns the l1 value.")
178
179 .def("scaleFactor", &ComponentInfo::scaleFactor, (arg("self"), arg("index")),
180 "Returns the scale factor for the component identified by 'index'.")
181
182 .def("setScaleFactor", &ComponentInfo::setScaleFactor, (arg("self"), arg("index"), arg("scaleFactor")),
183 "Set the scale factor of the component identifed by 'index'.")
184
185 .def("hasValidShape", &ComponentInfo::hasValidShape, (arg("self"), arg("index")),
186 "Returns True if the component identified by 'index' has a valid "
187 "shape.")
188
189 .def("shape", &ComponentInfo::shape, (arg("self"), arg("index")),
190 return_value_policy<reference_existing_object>(),
191 "Returns the shape of the component identified by 'index'.")
192
193 .def("solidAngle", &solidAngle, (arg("self"), arg("index"), arg("observer")),
194 "Returns the solid angle of the component identified by 'index' as "
195 "seen from the observer position.")
196
197 .def("componentType", &ComponentInfo::componentType, (arg("self"), arg("index")),
198 "Returns the ComponentType of the component identified by 'index'.")
199
200 .def("isGridDetector", &ComponentInfo::isGridDetector, (arg("self"), arg("index")),
201 "Returns True if the component identified by 'index' is a Rectangular or Grid "
202 "bank. Every pixelGrid* accessor requires this to be True.")
203
204 .def("pixelGridNX", &pixelGridField<&PixelGridComponent::nX>, (arg("self"), arg("index")),
205 "Returns the number of pixels in the X (horizontal) direction of the "
206 "Rectangular/Grid bank identified by 'index'. Raises RuntimeError if the "
207 "component is not a Rectangular or Grid bank.")
208
209 .def("pixelGridNY", &pixelGridField<&PixelGridComponent::nY>, (arg("self"), arg("index")),
210 "Returns the number of pixels in the Y (vertical) direction of the "
211 "Rectangular/Grid bank identified by 'index'. Raises RuntimeError if the "
212 "component is not a Rectangular or Grid bank.")
213
214 .def("pixelGridNZ", &pixelGridField<&PixelGridComponent::nZ>, (arg("self"), arg("index")),
215 "Returns the number of pixels in the Z (usually beam) direction of the "
216 "Rectangular/Grid bank identified by 'index', or 0 for a 2D (rectangular) "
217 "bank. Raises RuntimeError if the component is not a Rectangular or Grid bank.")
218
219 .def("pixelGridXStart", &pixelGridField<&PixelGridComponent::xStart>, (arg("self"), arg("index")),
220 "Returns the X position of pixel (0, 0, 0), in the local (unrotated, unscaled) "
221 "frame of the Rectangular/Grid bank identified by 'index'. Raises RuntimeError "
222 "if the component is not a Rectangular or Grid bank.")
223
224 .def("pixelGridYStart", &pixelGridField<&PixelGridComponent::yStart>, (arg("self"), arg("index")),
225 "Returns the Y position of pixel (0, 0, 0), in the local (unrotated, unscaled) "
226 "frame of the Rectangular/Grid bank identified by 'index'. Raises RuntimeError "
227 "if the component is not a Rectangular or Grid bank.")
228
229 .def("pixelGridZStart", &pixelGridField<&PixelGridComponent::zStart>, (arg("self"), arg("index")),
230 "Returns the Z position of pixel (0, 0, 0), in the local (unrotated, unscaled) "
231 "frame of the Rectangular/Grid bank identified by 'index'. Raises RuntimeError "
232 "if the component is not a Rectangular or Grid bank.")
233
234 .def("pixelGridXStep", &pixelGridField<&PixelGridComponent::xStep>, (arg("self"), arg("index")),
235 "Returns the step size between neighbouring pixels along X for the "
236 "Rectangular/Grid bank identified by 'index'. Raises RuntimeError if the "
237 "component is not a Rectangular or Grid bank.")
238
239 .def("pixelGridYStep", &pixelGridField<&PixelGridComponent::yStep>, (arg("self"), arg("index")),
240 "Returns the step size between neighbouring pixels along Y for the "
241 "Rectangular/Grid bank identified by 'index'. Raises RuntimeError if the "
242 "component is not a Rectangular or Grid bank.")
243
244 .def("pixelGridZStep", &pixelGridField<&PixelGridComponent::zStep>, (arg("self"), arg("index")),
245 "Returns the step size between neighbouring pixels along Z for the "
246 "Rectangular/Grid bank identified by 'index'. Raises RuntimeError if the "
247 "component is not a Rectangular or Grid bank.")
248
249 .def("pixelGridIdStart", &pixelGridField<&PixelGridComponent::idStart>, (arg("self"), arg("index")),
250 "Returns the detector ID of the first pixel of the Rectangular/Grid bank "
251 "identified by 'index'. Raises RuntimeError if the component is not a "
252 "Rectangular or Grid bank.")
253
254 .def("pixelGridIdStep", &pixelGridField<&PixelGridComponent::idStep>, (arg("self"), arg("index")),
255 "Returns the detector ID step between pixels along the first-filled axis of "
256 "the Rectangular/Grid bank identified by 'index'. Raises RuntimeError if the "
257 "component is not a Rectangular or Grid bank.")
258
259 .def("pixelGridIdStepByRow", &pixelGridField<&PixelGridComponent::idStepByRow>, (arg("self"), arg("index")),
260 "Returns the detector ID step between rows along the second-filled axis of "
261 "the Rectangular/Grid bank identified by 'index'. Raises RuntimeError if the "
262 "component is not a Rectangular or Grid bank.")
263
264 .def("pixelGridMinDetectorID", &pixelGridField<&PixelGridComponent::minDetectorID>, (arg("self"), arg("index")),
265 "Returns the minimum detector ID in the Rectangular/Grid bank identified by "
266 "'index'. Raises RuntimeError if the component is not a Rectangular or Grid bank.")
267
268 .def("pixelGridMaxDetectorID", &pixelGridField<&PixelGridComponent::maxDetectorID>, (arg("self"), arg("index")),
269 "Returns the maximum detector ID in the Rectangular/Grid bank identified by "
270 "'index'. Raises RuntimeError if the component is not a Rectangular or Grid bank.")
271
272 .def("pixelGridIdFillOrder", &pixelGridIdFillOrder, (arg("self"), arg("index")),
273 "Returns the axis order in which detector IDs are filled for the "
274 "Rectangular/Grid bank identified by 'index', as a 3-character string "
275 "permutation of 'x', 'y' and 'z'. Raises RuntimeError if the component is not "
276 "a Rectangular or Grid bank.")
277
278 .def("detectorIndexAtXYZ", &ComponentInfo::detectorIndexAtXYZ,
279 (arg("self"), arg("index"), arg("x"), arg("y"), arg("z")),
280 "Returns the detector index of the pixel at (x, y, z) within the "
281 "Rectangular/Grid bank identified by 'index'.")
282
283 .def("indexOfAny", &ComponentInfo::indexOfAny, (arg("self"), arg("name")),
284 "Returns the index of any component matching name. Raises "
285 "ValueError if name not found")
286
287 .def("uniqueName", &ComponentInfo::uniqueName, (arg("self"), arg("name")),
288 "Returns True if the name is a unique single occurance. Zero occurances yields False.")
289
290 .def("root", &ComponentInfo::root, arg("self"), "Returns the index of the root component")
291 .def("getMemorySize", &ComponentInfo::getMemorySize, arg("self"),
292 "Return the memory footprint of the component info in bytes.")
293 .def("shapeToComponentIndices", &shapeToComponentIndices, arg("self"),
294 "Returns a mapping of shapes to the indices of components with that shape.");
295}
std::map< DeltaEMode::Type, std::string > index
SpectrumInfoPythonIterator make_pyiterator(SpectrumInfo &spectrumInfo)
void export_ComponentInfo()
Mantid::Kernel::Quat(ComponentInfo::* rotation)(const size_t) const
void(ComponentInfo::* setPosition)(const size_t, const Mantid::Kernel::V3D &)
void(ComponentInfo::* setRotation)(const size_t, const Mantid::Kernel::Quat &)
Mantid::Kernel::V3D(ComponentInfo::* position)(const size_t) const
ComponentInfo : Provides a component centric view on to the instrument.
bool hasParent(const size_t componentIndex) const
std::unordered_map< std::shared_ptr< const Geometry::IObject >, std::vector< size_t > > shapeToComponentIndices() const
Build a map from each unique shape to the list of component indices that share it.
size_t indexOfAny(const std::string &name) const
bool hasEquivalentSource(const ComponentInfo &other) const
double solidAngle(const size_t componentIndex, const Geometry::SolidAngleParams &params) const
size_t parent(const size_t componentIndex) const
bool isGridDetector(size_t const componentIndex) const
const std::vector< size_t > & children(size_t componentIndex) const
std::vector< size_t > componentsInSubtree(size_t componentIndex) const
bool hasValidShape(const size_t componentIndex) const
Beamline::PixelGridComponent pixelGridComponent(const size_t componentIndex) const
bool hasEquivalentSample(const ComponentInfo &other) const
void setScaleFactor(const size_t componentIndex, const Kernel::V3D &scaleFactor)
std::vector< size_t > detectorsInSubtree(size_t componentIndex) const
bool isDetector(const size_t componentIndex) const
bool uniqueName(const std::string &name) const
size_t detectorIndexAtXYZ(const size_t componentIndex, const int x, const int y, const int z) const
Kernel::V3D relativePosition(const size_t componentIndex) const
const std::string & name(const size_t componentIndex) const
size_t getMemorySize() const
Return memory used by the component info, in bytes.
Kernel::Quat relativeRotation(const size_t componentIndex) const
const Geometry::IObject & shape(const size_t componentIndex) const
Beamline::ComponentType componentType(const size_t componentIndex) const
Kernel::V3D scaleFactor(const size_t componentIndex) const
Class for quaternions.
Definition Quat.h:39
Class for 3D vectors.
Definition V3D.h:34
Helper class which provides the Collimation Length for SANS instruments.
Implements a return value policy that returns a numpy array from a rerence to a std::vector.