Mantid
Loading...
Searching...
No Matches
DetectorInfo.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 +
10#include "MantidKernel/Quat.h"
11#include "MantidKernel/V3D.h"
14#include "MantidPythonInterface/geometry/DetectorInfoPythonIterator.h"
15#include <boost/iterator/iterator_facade.hpp>
16#include <boost/python/class.hpp>
17#include <boost/python/copy_const_reference.hpp>
18#include <boost/python/copy_non_const_reference.hpp>
19#include <boost/python/iterator.hpp>
20#include <boost/python/return_by_value.hpp>
21#include <boost/python/return_value_policy.hpp>
22#include <iterator>
23
24#define PY_ARRAY_UNIQUE_SYMBOL GEOMETRY_ARRAY_API
25#define NO_IMPORT_ARRAY
26#include <numpy/ndarrayobject.h>
27
31using Mantid::PythonInterface::DetectorInfoPythonIterator;
32
35using namespace boost::python;
36using namespace Mantid::PythonInterface;
37
38namespace {
39// Helper method to make the python iterator
40DetectorInfoPythonIterator make_pyiterator(DetectorInfo &detectorInfo) {
41 return DetectorInfoPythonIterator(detectorInfo);
42}
44using return_readonly_numpy = return_value_policy<Policies::VectorRefToNumpy<Converters::WrapReadOnly>>;
45
46PyObject *numpyArrayFromVector(const std::vector<V3D> &vec) {
47 const size_t n_detectors = vec.size();
48 constexpr size_t vec_size = 3;
49 npy_intp dims[2] = {static_cast<npy_intp>(n_detectors), vec_size};
50 PyObject *numpy_array = PyArray_SimpleNew(2, dims, NPY_DOUBLE);
51 if (!numpy_array) {
52 PyErr_SetString(PyExc_RuntimeError, "Failed to create numpy array");
53 throw boost::python::error_already_set();
54 }
55 double *data = static_cast<double *>(PyArray_DATA(reinterpret_cast<PyArrayObject *>(numpy_array)));
56 for (size_t i = 0; i < n_detectors; ++i) {
57 const size_t base_index = i * vec_size;
58 data[base_index + 0] = vec[i].X();
59 data[base_index + 1] = vec[i].Y();
60 data[base_index + 2] = vec[i].Z();
61 }
62 return numpy_array;
63}
64
65PyObject *allPositions(const DetectorInfo &self) {
66 const std::vector<V3D> positions = self.allPositions();
67 return numpyArrayFromVector(positions);
68}
69
70PyObject *allScaleFactors(const DetectorInfo &self) {
71 const std::vector<V3D> positions = self.allScaleFactors();
72 return numpyArrayFromVector(positions);
73}
74
75PyObject *allRotations(const DetectorInfo &self) {
76 const std::vector<Quat> rotations = self.allRotations();
77 const size_t n_detectors = rotations.size();
78 const size_t quat_size = 4;
79 npy_intp dims[2] = {static_cast<npy_intp>(n_detectors), quat_size};
80 PyObject *numpy_rotations_array = PyArray_SimpleNew(2, dims, NPY_DOUBLE);
81 if (!numpy_rotations_array) {
82 PyErr_SetString(PyExc_RuntimeError, "Failed to create numpy array");
83 throw boost::python::error_already_set();
84 }
85 double *data = static_cast<double *>(PyArray_DATA(reinterpret_cast<PyArrayObject *>(numpy_rotations_array)));
86 for (size_t i = 0; i < n_detectors; ++i) {
87 const size_t base_index = i * quat_size;
88 data[base_index + 0] = rotations[i].imagI();
89 data[base_index + 1] = rotations[i].imagJ();
90 data[base_index + 2] = rotations[i].imagK();
91 data[base_index + 3] = rotations[i].real();
92 }
93 return numpy_rotations_array;
94}
95
96} // namespace
97
98// Export DetectorInfo
100
101 // Function pointers to distinguish between overloaded versions
102 bool (DetectorInfo::*isMonitor)(const size_t) const = &DetectorInfo::isMonitor;
103
104 bool (DetectorInfo::*isMasked)(const size_t) const = &DetectorInfo::isMasked;
105
106 double (DetectorInfo::*twoTheta)(const size_t) const = &DetectorInfo::twoTheta;
107
108 double (DetectorInfo::*signedTwoTheta)(const size_t) const = &DetectorInfo::signedTwoTheta;
109
110 double (DetectorInfo::*azimuthal)(const size_t) const = &DetectorInfo::azimuthal;
111
113
115
116 void (DetectorInfo::*setMasked)(const size_t, bool) = &DetectorInfo::setMasked;
117
118 double (DetectorInfo::*l2)(const size_t) const = &DetectorInfo::l2;
119
120 // Export to Python
121 class_<DetectorInfo, boost::noncopyable>("DetectorInfo", no_init)
122
123 .def("__iter__", make_pyiterator)
124
125 .def("__len__", &DetectorInfo::size, (arg("self")),
126 "Returns the size of the DetectorInfo, i.e., the number of "
127 "detectors in the instrument.")
128
129 .def("size", &DetectorInfo::size, (arg("self")),
130 "Returns the size of the DetectorInfo, i.e., the number of "
131 "detectors in the instrument.")
132
133 .def("indexOf", &DetectorInfo::indexOf, (arg("self"), arg("detId")),
134 "Returns the index of the detector with the given id.")
135
136 .def("isMonitor", isMonitor, (arg("self"), arg("index")), "Returns True if the detector is a monitor.")
137
138 .def("isMasked", isMasked, (arg("self"), arg("index")), "Returns True if the detector is masked.")
139
140 .def("setMasked", setMasked, (arg("self"), arg("index"), arg("masked")),
141 "Set the mask flag of the detector where the detector is identified "
142 "by 'index'.")
143
144 .def("clearMaskFlags", &DetectorInfo::clearMaskFlags, (arg("self")), "Sets all mask flags to false (unmasked).")
145
146 .def("isEquivalent", &DetectorInfo::isEquivalent, (arg("self"), arg("other")),
147 "Returns True if the content of this "
148 "detector is equivalent to the content "
149 "of the other detector.")
150
151 .def("twoTheta", twoTheta, (arg("self"), arg("index")),
152 "Returns 2 theta (scattering angle w.r.t beam direction).")
153 .def("signedTwoTheta", signedTwoTheta, (arg("self"), arg("index")),
154 "Returns signed 2 theta (signed scattering angle w.r.t beam direction).")
155 .def("azimuthal", azimuthal, (arg("self"), arg("index")),
156 "Returns the out-of-plane angle in radians angle w.r.t. to "
157 "vecPointingHorizontal")
158 .def("position", position, (arg("self"), arg("index")),
159 "Returns the absolute position of the detector where the detector "
160 "is identified by 'index'.")
161 .def("allPositions", &allPositions, (arg("self")),
162 "Returns the absolute positions of all detectors as a numpy array.")
163 .def("rotation", rotation, (arg("self"), arg("index")),
164 "Returns the absolute rotation of the detector where the detector "
165 "is identified by 'index'.")
166 .def("allRotations", &allRotations, (arg("self")),
167 "Returns the absolute rotations of all detectors as a numpy array of quarternions, [i, j, k, w].")
168 .def("allScaleFactors", &allScaleFactors, (arg("self")),
169 "Returns the scale factors of all detectors as a numpy array.")
170 .def("detectorIDs", &DetectorInfo::detectorIDs, return_readonly_numpy(),
171 "Returns all detector ids sorted by detector index")
172 .def("l2", l2, (arg("self"), arg("index")), "Returns the l2 scattering distance")
173 .def("l1", &DetectorInfo::l1, arg("self"), "Returns the l1 scattering distance")
174 .def("hasMaskedDetectors", &DetectorInfo::hasMaskedDetectors, arg("self"),
175 "Returns if there are masked detectors")
176 .def("getMemorySize", &DetectorInfo::getMemorySize, arg("self"),
177 "Return the memory footprint of the detector info in bytes.");
178}
double position
Definition GetAllEi.cpp:154
tagPyArrayObject PyArrayObject
std::vector< T > const * vec
SpectrumInfoPythonIterator make_pyiterator(SpectrumInfo &spectrumInfo)
Mantid::Kernel::Quat(ComponentInfo::* rotation)(const size_t) const
void export_DetectorInfo()
DetectorInfoIterator for random access iteration over DetectorInfo.
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
double twoTheta(const size_t index) const
Returns 2 theta (scattering angle w.r.t. to beam direction).
double l2(const size_t index) const
Returns L2 (distance from sample to spectrum).
std::vector< Kernel::Quat > allRotations() const
Returns the absolute rotations of all detectors in a vector ordered by index.
bool hasMaskedDetectors() const
Returns true if there are masked detectors.
Kernel::Quat rotation(const size_t index) const
Returns the rotation of the detector with given index.
bool isMasked(const size_t index) const
Returns true if the detector is masked.
void setMasked(const size_t index, bool masked)
Set the mask flag of the detector with given index. Not thread safe.
std::vector< Kernel::V3D > allPositions() const
Returns the absolute positions of all detectors in a vector ordered by index.
const std::vector< detid_t > & detectorIDs() const
Returns a sorted vector of all detector IDs.
Kernel::V3D position(const size_t index) const
Returns the position of the detector with given index.
size_t getMemorySize() const
Return memory used by the detector info, in bytes.
void clearMaskFlags()
Sets all mask flags to false (unmasked).
bool isEquivalent(const DetectorInfo &other) const
Returns true if the content of this is equivalent to the content of other.
double signedTwoTheta(const size_t index) const
Returns signed 2 theta (signed scattering angle w.r.t. to beam direction).
double l1() const
Returns L1 (distance from source to sample).
std::vector< Kernel::V3D > allScaleFactors() const
Returns the scale factors of all detectors in a vector ordered by index.
size_t indexOf(const detid_t id) const
Returns the index of the detector with the given detector ID.
size_t size() const
Returns the size of the DetectorInfo, i.e., the number of detectors in the instrument.
bool isMonitor(const size_t index) const
Returns true if the detector is a monitor.
double azimuthal(const size_t index) const
Class for quaternions.
Definition Quat.h:39
Class for 3D vectors.
Definition V3D.h:34