Mantid
Loading...
Searching...
No Matches
InstrumentVisitor.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/ComponentInfo.h"
9#include "MantidBeamline/DetectorInfo.h"
22
23#include <algorithm>
24#include <memory>
25#include <numeric>
26
27namespace Mantid::Geometry {
28
29namespace {
30std::shared_ptr<const std::unordered_map<detid_t, size_t>> makeDetIdToIndexMap(const std::vector<detid_t> &detIds) {
31
32 const size_t nDetIds = detIds.size();
33 auto detIdToIndex = std::make_shared<std::unordered_map<detid_t, size_t>>();
34 detIdToIndex->reserve(nDetIds);
35 for (size_t i = 0; i < nDetIds; ++i) {
36 (*detIdToIndex)[detIds[i]] = i;
37 }
38 return detIdToIndex;
39}
40
41void clearLegacyParameters(ParameterMap *pmap, const IComponent &comp) {
42 if (!pmap)
43 return;
44 pmap->clearParametersByName(ParameterMap::pos(), &comp);
45 pmap->clearParametersByName(ParameterMap::posx(), &comp);
46 pmap->clearParametersByName(ParameterMap::posy(), &comp);
47 pmap->clearParametersByName(ParameterMap::posz(), &comp);
48 pmap->clearParametersByName(ParameterMap::rot(), &comp);
49 pmap->clearParametersByName(ParameterMap::rotx(), &comp);
50 pmap->clearParametersByName(ParameterMap::roty(), &comp);
51 pmap->clearParametersByName(ParameterMap::rotz(), &comp);
52 pmap->clearParametersByName(ParameterMap::scale(), &comp);
53}
54
55bool hasValidShape(const ObjCompAssembly &obj) {
56 const auto *shape = obj.shape().get();
57 return shape != nullptr && shape->hasValidShape();
58}
59} // namespace
60
65InstrumentVisitor::InstrumentVisitor(std::shared_ptr<const Instrument> instrument)
66 : m_orderedDetectorIds(
67 std::make_shared<std::vector<detid_t>>(instrument->getDetectorIDs(false /*Do not skip monitors*/))),
68 m_componentIds(std::make_shared<std::vector<ComponentID>>(m_orderedDetectorIds->size(), nullptr)),
69 m_assemblySortedDetectorIndices(std::make_shared<std::vector<size_t>>()),
70 m_assemblySortedComponentIndices(std::make_shared<std::vector<size_t>>()),
71 m_parentComponentIndices(std::make_shared<std::vector<size_t>>(m_orderedDetectorIds->size(), 0)),
72 m_children(std::make_shared<std::vector<std::vector<size_t>>>()),
73 m_detectorRanges(std::make_shared<std::vector<std::pair<size_t, size_t>>>()),
74 m_componentRanges(std::make_shared<std::vector<std::pair<size_t, size_t>>>()),
75 m_componentIdToIndexMap(std::make_shared<std::unordered_map<Mantid::Geometry::IComponent *, size_t>>()),
76 m_detectorIdToIndexMap(makeDetIdToIndexMap(*m_orderedDetectorIds)),
77 m_positions(std::make_shared<std::vector<Eigen::Vector3d>>()),
78 m_detectorPositions(std::make_shared<std::vector<Eigen::Vector3d>>(m_orderedDetectorIds->size())),
79 m_rotations(std::make_shared<std::vector<Eigen::Quaterniond, Eigen::aligned_allocator<Eigen::Quaterniond>>>()),
80 m_detectorRotations(
81 std::make_shared<std::vector<Eigen::Quaterniond, Eigen::aligned_allocator<Eigen::Quaterniond>>>(
82 m_orderedDetectorIds->size())),
83 m_monitorIndices(std::make_shared<std::vector<size_t>>()), m_instrument(std::move(instrument)), m_pmap(nullptr),
84 m_nullShape(std::make_shared<const CSGObject>()),
85 m_shapes(
86 std::make_shared<std::vector<std::shared_ptr<const IObject>>>(m_orderedDetectorIds->size(), m_nullShape)),
87 m_scaleFactors(
88 std::make_shared<std::vector<Eigen::Vector3d>>(m_orderedDetectorIds->size(), Eigen::Vector3d{1, 1, 1})),
89 m_componentType(std::make_shared<std::vector<Beamline::ComponentType>>()),
90 m_names(std::make_shared<std::vector<std::string>>(m_orderedDetectorIds->size())) {
91 if (m_instrument->isParametrized()) {
92 m_pmap = m_instrument->getParameterMap().get();
93 }
94
95 m_sourceId = nullptr;
96 m_sampleId = nullptr;
97
98 // To prevent warning generation. Do not even try to get the source or sample
99 // id if the instrument is empty.
100 if (!m_instrument->isEmptyInstrument()) {
101
102 m_sourceId = m_instrument->getSource() ? m_instrument->getSource()->getComponentID() : nullptr;
103 m_sampleId = m_instrument->getSample() ? m_instrument->getSample()->getComponentID() : nullptr;
104 }
105
106 const auto nDetectors = m_orderedDetectorIds->size();
107 m_assemblySortedDetectorIndices->reserve(nDetectors); // Exact
108 m_componentIdToIndexMap->reserve(nDetectors); // Approximation
109}
110
112 if (m_pmap && m_pmap->empty()) {
113 // Go through the base instrument for speed.
114 m_instrument->baseInstrument()->registerContents(*this);
115 } else
116 m_instrument->registerContents(*this);
117}
118
120 const size_t componentIndex = m_componentIds->size();
121 const ComponentID componentId = component.getComponentID();
122 markAsSourceOrSample(componentId, componentIndex);
123 // Record the ID -> index mapping
124 (*m_componentIdToIndexMap)[componentId] = componentIndex;
125 // For any non-detector we extend the m_componentIds from the back
126 m_componentIds->emplace_back(componentId);
127 m_positions->emplace_back(Kernel::toVector3d(component.getPos()));
128 m_rotations->emplace_back(Kernel::toQuaterniond(component.getRotation()));
129 m_shapes->emplace_back(m_nullShape);
130 m_scaleFactors->emplace_back(Kernel::toVector3d(component.getScaleFactor()));
131 m_names->emplace_back(component.getName());
132 clearLegacyParameters(m_pmap, component);
133 return componentIndex;
134}
135
137
138 std::vector<IComponent_const_sptr> assemblyChildren;
139 assembly.getChildren(assemblyChildren, false /*is recursive*/);
140
141 const size_t detectorStart = m_assemblySortedDetectorIndices->size();
142 const size_t componentStart = m_assemblySortedComponentIndices->size();
143 std::vector<size_t> children(assemblyChildren.size());
144 for (size_t i = 0; i < assemblyChildren.size(); ++i) {
145 // register everything under this assembly
146 children[i] = assemblyChildren[i]->registerContents(*this);
147 }
148 const size_t detectorStop = m_assemblySortedDetectorIndices->size();
149 const size_t componentIndex = commonRegistration(assembly);
150 m_componentType->emplace_back(Beamline::ComponentType::Unstructured);
151 m_assemblySortedComponentIndices->emplace_back(componentIndex);
152 // Unless this is the root component this parent is not correct and will be
153 // updated later in the register call of the parent.
154 m_parentComponentIndices->emplace_back(componentIndex);
155 const size_t componentStop = m_assemblySortedComponentIndices->size();
156
157 m_detectorRanges->emplace_back(detectorStart, detectorStop);
158 m_componentRanges->emplace_back(std::make_pair(componentStart, componentStop));
159
160 // Now that we know what the index of the parent is we can apply it to the
161 // children
162 for (const auto &child : children) {
163 (*m_parentComponentIndices)[child] = componentIndex;
164 }
165 m_children->emplace_back(std::move(children));
166 return componentIndex;
167}
168
175 /*
176 * For a generic leaf component we extend the component ids list, but
177 * the detector indexes entries will of course be empty
178 */
179 m_detectorRanges->emplace_back(std::make_pair(0, 0)); // Represents an empty range
180 // Record the ID -> index mapping
181 const size_t componentIndex = commonRegistration(component);
182 m_componentType->emplace_back(Beamline::ComponentType::Generic);
183
184 const size_t componentStart = m_assemblySortedComponentIndices->size();
185 m_componentRanges->emplace_back(std::make_pair(componentStart, componentStart + 1));
186 m_assemblySortedComponentIndices->emplace_back(componentIndex);
187 // Unless this is the root component this parent is not correct and will be
188 // updated later in the register call of the parent.
189 m_parentComponentIndices->emplace_back(componentIndex);
190 // Generic components are not assemblies and do not therefore have children.
191 m_children->emplace_back();
192 return componentIndex;
193}
194
201 /*
202 * For a generic leaf component we extend the component ids list, but
203 * the detector indexes entries will of course be empty
204 */
205 m_detectorRanges->emplace_back(0, 0); // Represents an empty range
206 // Record the ID -> index mapping
207 const size_t componentIndex = commonRegistration(component);
208 m_componentType->emplace_back(Beamline::ComponentType::Infinite);
209
210 const size_t componentStart = m_assemblySortedComponentIndices->size();
211 m_componentRanges->emplace_back(componentStart, componentStart + 1);
212 m_assemblySortedComponentIndices->emplace_back(componentIndex);
213 // Unless this is the root component this parent is not correct and will be
214 // updated later in the register call of the parent.
215 m_parentComponentIndices->emplace_back(componentIndex);
216 // Generic components are not assemblies and do not therefore have children.
217 m_children->emplace_back();
218 return componentIndex;
219}
220
227 auto index = registerGenericComponent(objComponent);
228 (*m_shapes)[index] = objComponent.shape();
229 return index;
230}
231
238 auto index = registerComponentAssembly(bank);
239 size_t rangesIndex = index - m_orderedDetectorIds->size();
240 (*m_componentType)[rangesIndex] = Beamline::ComponentType::Rectangular;
241 return index;
242}
243
250 auto index = registerComponentAssembly(bank);
251 size_t rangesIndex = index - m_orderedDetectorIds->size();
252 (*m_componentType)[rangesIndex] = Beamline::ComponentType::Grid;
253 return index;
254}
255
262 auto index = registerInfiniteComponent(objComponent);
263 (*m_shapes)[index] = objComponent.shape();
264 return index;
265}
266
273 auto index = registerComponentAssembly(bank);
274 size_t rangesIndex = index - m_orderedDetectorIds->size();
275 (*m_componentType)[rangesIndex] = Beamline::ComponentType::Structured;
276 return index;
277}
278
281 (*m_shapes)[index] = obj.shape();
282 if (hasValidShape(obj)) {
283 size_t rangesIndex = index - m_orderedDetectorIds->size();
284 (*m_componentType)[rangesIndex] = Beamline::ComponentType::OutlineComposite;
285 }
286 return index;
287}
288
289void InstrumentVisitor::markAsSourceOrSample(ComponentID componentId, const size_t componentIndex) {
290 if (componentId == m_sampleId) {
291 m_sampleIndex = componentIndex;
292 } else if (componentId == m_sourceId) {
293 m_sourceIndex = componentIndex;
294 }
295}
296
303 auto detectorIndex = m_detectorIdToIndexMap->at(detector.getID());
304
305 /* Already allocated we just need to index into the inital front-detector
306 * part of the collection.
307 * 1. Guarantee on grouping detectors by type such that the first n
308 * components
309 * are detectors.
310 * 2. Guarantee on ordering such that the
311 * detectorIndex == componentIndex for all detectors.
312 */
313 // Record the ID -> component index mapping
314 (*m_componentIdToIndexMap)[detector.getComponentID()] = detectorIndex;
315 (*m_componentIds)[detectorIndex] = detector.getComponentID();
317 (*m_detectorPositions)[detectorIndex] = Kernel::toVector3d(detector.getPos());
318 (*m_detectorRotations)[detectorIndex] = Kernel::toQuaterniond(detector.getRotation());
319 (*m_shapes)[detectorIndex] = detector.shape();
320 (*m_scaleFactors)[detectorIndex] = Kernel::toVector3d(detector.getScaleFactor());
321 if (m_instrument->isMonitorViaIndex(detectorIndex)) {
322 m_monitorIndices->emplace_back(detectorIndex);
323 }
324 (*m_names)[detectorIndex] = detector.getName();
325 clearLegacyParameters(m_pmap, detector);
326
327 /* Note that positions and rotations for detectors are currently
328 NOT stored! These go into DetectorInfo at present. emplace_back works for
329 other Component types because Detectors are always come first in the resultant
330 component list
331 forming a contiguous block.
332 */
334 detectorIndex); // TODO. Optimisation. Cannot have a
335 // detector that is either source or
336 // sample. So delete this.
337 return detectorIndex;
338}
339
347std::shared_ptr<const std::vector<Mantid::Geometry::ComponentID>> InstrumentVisitor::componentIds() const {
348 return m_componentIds;
349}
350
356size_t InstrumentVisitor::size() const { return m_componentIds->size(); }
357
358bool InstrumentVisitor::isEmpty() const { return size() == 0; }
359
360std::shared_ptr<const std::unordered_map<Mantid::Geometry::IComponent *, size_t>>
363}
364
365std::shared_ptr<const std::unordered_map<detid_t, size_t>> InstrumentVisitor::detectorIdToIndexMap() const {
367}
368
369std::unique_ptr<Beamline::ComponentInfo> InstrumentVisitor::componentInfo() const {
370 return std::make_unique<Mantid::Beamline::ComponentInfo>(
374}
375
376std::unique_ptr<Beamline::DetectorInfo> InstrumentVisitor::detectorInfo() const {
377 return std::make_unique<Mantid::Beamline::DetectorInfo>(*m_detectorPositions, *m_detectorRotations,
379}
380
381std::shared_ptr<std::vector<detid_t>> InstrumentVisitor::detectorIds() const { return m_orderedDetectorIds; }
382
383std::pair<std::unique_ptr<ComponentInfo>, std::unique_ptr<DetectorInfo>> InstrumentVisitor::makeWrappers() const {
384 auto compInfo = componentInfo();
385 auto detInfo = detectorInfo();
386 // Cross link Component and Detector info objects
387 compInfo->setDetectorInfo(detInfo.get());
388
389 auto compInfoWrapper =
390 std::make_unique<ComponentInfo>(std::move(compInfo), componentIds(), componentIdToIndexMap(), m_shapes);
391 auto detInfoWrapper =
392 std::make_unique<DetectorInfo>(std::move(detInfo), m_instrument, detectorIds(), detectorIdToIndexMap());
393
394 return {std::move(compInfoWrapper), std::move(detInfoWrapper)};
395}
396
397std::pair<std::unique_ptr<ComponentInfo>, std::unique_ptr<DetectorInfo>>
399 // Visitee instrument is base instrument if no ParameterMap
400 const auto visiteeInstrument =
401 pmap ? ParComponentFactory::createInstrument(std::shared_ptr<const Instrument>(&instrument, NoDeleting()),
402 std::shared_ptr<ParameterMap>(pmap, NoDeleting()))
403 : std::shared_ptr<const Instrument>(&instrument, NoDeleting());
404 InstrumentVisitor visitor(visiteeInstrument);
405 visitor.walkInstrument();
406 return visitor.makeWrappers();
407}
408} // namespace Mantid::Geometry
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
IntArray detectorIndex
double obj
the value of the quadratic function
Constructive Solid Geometry object.
Definition: CSGObject.h:51
Class for Assembly of geometric components.
Definition: ICompAssembly.h:30
virtual void getChildren(std::vector< IComponent_const_sptr > &outVector, bool recursive) const =0
Get all children.
base class for Geometric IComponent
Definition: IComponent.h:51
virtual Kernel::V3D getPos() const =0
Get the position of the IComponent. Tree structure is traverse through the.
virtual Kernel::Quat getRotation() const =0
Get the absolute orientation of the IComponent.
virtual Kernel::V3D getScaleFactor() const
Gets the scaling factor of the object for the Object Component.
Definition: IComponent.h:118
virtual ComponentID getComponentID() const =0
Returns the ComponentID - a unique identifier of the component.
virtual std::string getName() const =0
Get the IComponent name.
Interface class for detector objects.
Definition: IDetector.h:43
virtual detid_t getID() const =0
Get the detector ID.
Object Component class, this class brings together the physical attributes of the component to the po...
Definition: IObjComponent.h:37
virtual const std::shared_ptr< const IObject > shape() const =0
Returns the shape of the Object.
IObject : Interface for geometry objects.
Definition: IObject.h:41
InstrumentVisitor : Visitor for components with access to Info wrapping features.
std::shared_ptr< std::vector< std::pair< size_t, size_t > > > m_detectorRanges
Only Assemblies and other NON-detectors yield detector ranges.
std::shared_ptr< const std::unordered_map< detid_t, size_t > > m_detectorIdToIndexMap
Detector ID -> index mappings.
int64_t m_sourceIndex
Source index to set.
std::shared_ptr< std::vector< size_t > > m_assemblySortedComponentIndices
Component indexes sorted by assembly.
std::unique_ptr< Beamline::ComponentInfo > componentInfo() const
Mantid::Geometry::ParameterMap * m_pmap
Parameter map to purge.
InstrumentVisitor(std::shared_ptr< const Instrument > instrument)
Constructor.
virtual size_t registerComponentAssembly(const Mantid::Geometry::ICompAssembly &assembly) override
std::shared_ptr< std::vector< detid_t > > m_orderedDetectorIds
Detector indices.
size_t size() const
InstrumentVisitor::size.
std::shared_ptr< const Mantid::Geometry::IObject > m_nullShape
Null shared (empty shape)
std::shared_ptr< std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > > m_rotations
Rotations for non-detectors.
virtual size_t registerGenericObjComponent(const Mantid::Geometry::IObjComponent &objComponent) override
InstrumentVisitor::registerGenericObjComponent.
std::shared_ptr< std::vector< size_t > > m_assemblySortedDetectorIndices
Detector indexes sorted by assembly.
std::shared_ptr< std::vector< std::pair< size_t, size_t > > > m_componentRanges
Component ranges.
size_t commonRegistration(const Mantid::Geometry::IComponent &component)
Extract the common aspects relevant to all component types.
std::shared_ptr< std::vector< detid_t > > detectorIds() const
virtual size_t registerGridBank(const Mantid::Geometry::ICompAssembly &bank) override
Register a grid bank.
std::shared_ptr< std::vector< Eigen::Vector3d > > m_positions
Positions for non-detectors.
void markAsSourceOrSample(Mantid::Geometry::IComponent *componentId, const size_t componentIndex)
virtual size_t registerRectangularBank(const Mantid::Geometry::ICompAssembly &bank) override
Register a rectangular bank.
virtual size_t registerObjComponentAssembly(const ObjCompAssembly &obj) override
std::shared_ptr< std::vector< std::shared_ptr< const Mantid::Geometry::IObject > > > m_shapes
Shapes stored in fly-weight fashion.
virtual size_t registerDetector(const Mantid::Geometry::IDetector &detector) override
InstrumentVisitor::registerDetector.
std::shared_ptr< std::vector< std::vector< size_t > > > m_children
Stores instrument tree structure by storing children of all Components.
std::shared_ptr< std::vector< Eigen::Vector3d > > m_scaleFactors
Scale factors.
std::shared_ptr< std::unordered_map< Mantid::Geometry::IComponent *, size_t > > m_componentIdToIndexMap
Component ID -> Component Index map.
std::shared_ptr< std::vector< Mantid::Geometry::IComponent * > > m_componentIds
Detectors components always specified first.
std::shared_ptr< const std::unordered_map< Mantid::Geometry::IComponent *, size_t > > componentIdToIndexMap() const
std::shared_ptr< std::vector< Eigen::Vector3d > > m_detectorPositions
Positions for detectors.
std::shared_ptr< std::vector< Beamline::ComponentType > > m_componentType
Structured bank flag.
std::shared_ptr< const std::unordered_map< detid_t, size_t > > detectorIdToIndexMap() const
std::pair< std::unique_ptr< ComponentInfo >, std::unique_ptr< DetectorInfo > > makeWrappers() const
Mantid::Geometry::IComponent * m_sourceId
Source id to look for.
std::unique_ptr< Beamline::DetectorInfo > detectorInfo() const
virtual size_t registerStructuredBank(const Mantid::Geometry::ICompAssembly &bank) override
Register a structured bank.
std::shared_ptr< const std::vector< Mantid::Geometry::IComponent * > > componentIds() const
InstrumentVisitor::componentIds.
std::shared_ptr< std::vector< std::string > > m_names
Component names.
virtual size_t registerInfiniteComponent(const Mantid::Geometry::IComponent &component) override
InstrumentVisitor::registerInfiniteComponent.
int64_t m_sampleIndex
Sample index to set.
Mantid::Geometry::IComponent * m_sampleId
Sample id to look for.
std::shared_ptr< const Mantid::Geometry::Instrument > m_instrument
Instrument to build around.
std::shared_ptr< std::vector< size_t > > m_parentComponentIndices
Index of the parent component.
std::shared_ptr< std::vector< size_t > > m_monitorIndices
Monitor indexes for detectors.
virtual size_t registerInfiniteObjComponent(const IObjComponent &objComponent) override
InstrumentVisitor::registerInfiniteObjComponent.
virtual size_t registerGenericComponent(const Mantid::Geometry::IComponent &component) override
InstrumentVisitor::registerGenericComponent.
std::shared_ptr< std::vector< Eigen::Quaterniond, Eigen::aligned_allocator< Eigen::Quaterniond > > > m_detectorRotations
Rotations for detectors.
Base Instrument Class.
Definition: Instrument.h:47
Void deleter for shared pointers.
Class for Assembly of geometric components.
static std::shared_ptr< Instrument > createInstrument(const std::shared_ptr< const Instrument > &base, const std::shared_ptr< ParameterMap > &map)
Create a parameterized instrument from the given base and ParameterMap.
bool empty() const
Returns true if the map is empty, false otherwise.
Definition: ParameterMap.h:57
static const std::string & scale()
static const std::string & rot()
static const std::string & posz()
static const std::string & pos()
Return string to be used in the map.
static const std::string & rotz()
static const std::string & posy()
static const std::string & posx()
static const std::string & rotx()
static const std::string & roty()
Eigen::Vector3d toVector3d(const Kernel::V3D &vec)
Converts Kernel::V3D to Eigen::Vector3d.
Eigen::Quaterniond toQuaterniond(const Kernel::Quat &quat)
Converts Kernel::Quat to Eigen::Quaterniond.
Helper class which provides the Collimation Length for SANS instruments.
int32_t detid_t
Typedef for a detector ID.
Definition: SpectrumInfo.h:21
Generate a tableworkspace to store the calibration results.
STL namespace.