Mantid
Loading...
Searching...
No Matches
StructuredDetector.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 +
17#include "MantidKernel/Matrix.h"
18#include <algorithm>
19#include <boost/regex.hpp>
20#include <memory>
21#include <ostream>
22#include <stdexcept>
23
24namespace Mantid::Geometry {
25
26using Kernel::V3D;
27
31
41StructuredDetector::StructuredDetector(const std::string &name, IComponent *reference)
42 : CompAssembly(name, reference), IObjComponent(nullptr), m_base(nullptr) {
43 init();
44 this->setName(name);
45}
46
52 : CompAssembly(base, map), IObjComponent(nullptr), m_base(base) {
53 init();
54}
55
56bool StructuredDetector::compareName(const std::string &proposedMatch) {
57 static const boost::regex exp("StructuredDetector|structuredDetector|"
58 "structureddetector|structured_detector");
59
60 return boost::regex_match(proposedMatch, exp);
61}
62
64 m_xPixels = 0;
65 m_yPixels = 0;
66 m_minDetId = 0;
67 m_maxDetId = 0;
68 m_idStart = 0;
69 m_idFillByFirstY = false;
70 m_idStepByRow = 0;
71 m_idStep = 0;
72
74}
75
81
82//-------------------------------------------------------------------------------------------------
93std::shared_ptr<Detector> StructuredDetector::getAtXY(const size_t x, const size_t y) const {
94 if (x >= xPixels())
95 throw std::runtime_error("StructuredDetector::getAtXY: X specified is out of range.");
96 if (y >= yPixels())
97 throw std::runtime_error("StructuredDetector::getAtXY: Y specified is out of range.");
98
99 // Get to column
100 ICompAssembly_sptr xCol = std::dynamic_pointer_cast<ICompAssembly>(this->getChild(static_cast<int>(x)));
101 if (!xCol)
102 throw std::runtime_error("StructuredDetector::getAtXY: X specified is out of range.");
103 return std::dynamic_pointer_cast<Detector>(xCol->getChild(static_cast<int>(y)));
104}
105
115detid_t StructuredDetector::getDetectorIDAtXY(const size_t x, const size_t y) const {
116 const StructuredDetector *me = m_map == nullptr ? this : this->m_base;
117
118 if (me->m_idFillByFirstY)
119 return static_cast<detid_t>(me->m_idStart + x * me->m_idStepByRow + y * me->m_idStep);
120 else
121 return static_cast<detid_t>(me->m_idStart + y * me->m_idStepByRow + x * me->m_idStep);
122}
123
129std::pair<size_t, size_t> StructuredDetector::getXYForDetectorID(const detid_t detectorID) const {
130 const StructuredDetector *me = this;
131 if (m_map)
132 me = this->m_base;
133
134 int id = detectorID - me->m_idStart;
135
136 if ((me->m_idStepByRow == 0) || (me->m_idStep == 0))
137 return std::pair<int, int>(-1, -1);
138
139 int row = id / me->m_idStepByRow;
140 int col = (id % me->m_idStepByRow) / me->m_idStep;
141
142 if (me->m_idFillByFirstY) // x is the fast-changing axis
143 return std::pair<int, int>(row, col);
144 else
145 return std::pair<int, int>(col, row);
146}
147
151 if (m_map)
152 return m_base->m_xPixels;
153 else
154 return this->m_xPixels;
155}
156
163void StructuredDetector::setColors(const std::vector<int> &r, const std::vector<int> &g,
164 const std::vector<int> &b) const {
165 if (m_map)
166 m_base->setColors(r, g, b);
167 else {
168 this->r = r;
169 this->g = g;
170 this->b = b;
171 }
172}
173
176std::vector<int> const &StructuredDetector::getR() const {
177 if (m_map)
178 return m_base->getR();
179 else
180 return r;
181}
182
185std::vector<int> const &StructuredDetector::getG() const {
186 if (m_map)
187 return m_base->getG();
188 else
189 return g;
190}
191
194std::vector<int> const &StructuredDetector::getB() const {
195 if (m_map)
196 return m_base->getB();
197 else
198 return b;
199}
200
204 if (m_map)
205 return m_base->m_yPixels;
206 else
207 return this->m_yPixels;
208}
209
212 if (m_map)
213 return m_base->m_idStart;
214 else
215 return this->m_idStart;
216}
217
220 if (m_map)
221 return m_base->m_idFillByFirstY;
222 else
223 return this->m_idFillByFirstY;
224}
225
228 if (m_map)
229 return m_base->m_idStepByRow;
230 else
231 return this->m_idStepByRow;
232}
233
236 if (m_map)
237 return m_base->m_idStep;
238 else
239 return this->m_idStep;
240}
241
242std::vector<double> const &StructuredDetector::getXValues() const {
243 if (m_map)
244 return m_base->getXValues();
245 else
246 return this->m_xvalues;
247}
248
249std::vector<double> const &StructuredDetector::getYValues() const {
250 if (m_map)
251 return m_base->getYValues();
252 else
253 return this->m_yvalues;
254}
255
278void StructuredDetector::initialize(size_t xPixels, size_t yPixels, std::vector<double> &&x, std::vector<double> &&y,
279 bool isZBeam, detid_t idStart, bool idFillByFirstY, int idStepByRow, int idStep) {
280 if (m_map)
281 throw std::runtime_error("StructuredDetector::initialize() called for a "
282 "parametrized StructuredDetector");
283
286
295
296 // Some safety checks
297 if (m_xPixels == 0)
298 throw std::invalid_argument("StructuredDetector::initialize(): xPixels should be > 0");
299 if (m_yPixels == 0)
300 throw std::invalid_argument("StructuredDetector::initialize(): yPixels should be > 0");
301 if (x.size() != y.size())
302 throw std::invalid_argument("StructuredDetector::initialize(): x.size() should be = y.size()");
303 if (x.size() != (size_t)((m_xPixels + 1) * (m_yPixels + 1)))
304 throw std::invalid_argument("StructuredDetector::initialize(): x.size() "
305 "should be = (xPixels+1)*(yPixels+1)");
306 if (!isZBeam) // StructuredDetector only allows z-axis aligned beams.
307 throw std::invalid_argument("Expecting reference_frame to provide z as "
308 "beam axis. StructuredDetecor only allows "
309 "z-axis aligned beams.");
310
311 // Store vertices
312 m_xvalues = std::move(x);
313 m_yvalues = std::move(y);
314
316}
317
321 auto minDetId = m_idStart;
322 auto maxDetId = m_idStart;
323
324 for (size_t ix = 0; ix < m_xPixels; ix++) {
325 // Create an ICompAssembly for each x-column
326 std::ostringstream oss_col;
327
328 oss_col << this->getName() << "(x=" << ix << ")";
329 CompAssembly *xColumn = new CompAssembly(oss_col.str(), this);
330
331 for (size_t iy = 0; iy < m_yPixels; iy++) {
332 std::ostringstream oss;
333 oss << this->getName() << "(" << ix << "," << iy << ")";
334
335 // Calculate its id and set it.
336 auto id = this->getDetectorIDAtXY(ix, iy);
337
338 // Store min and max det IDs
339 // minimum structured detector id
340 if (id < minDetId) {
341 minDetId = id;
342 }
343 // maximum structured detector id
344 if (id > maxDetId) {
345 maxDetId = id;
346 }
347
348 // Create and store detector pixel
349 xColumn->add(addDetector(xColumn, oss.str(), ix, iy, id));
350 }
351 }
352
353 m_minDetId = minDetId;
354 m_maxDetId = maxDetId;
355}
356
366Detector *StructuredDetector::addDetector(CompAssembly *parent, const std::string &name, size_t x, size_t y,
367 detid_t id) {
368 auto w = m_xPixels + 1;
369
370 // Store hexahedral vertices for detector shape
371 auto xlb = m_xvalues[(y * w) + x];
372 auto xlf = m_xvalues[(y * w) + x + w];
373 auto xrf = m_xvalues[(y * w) + x + w + 1];
374 auto xrb = m_xvalues[(y * w) + x + 1];
375 auto ylb = m_yvalues[(y * w) + x];
376 auto ylf = m_yvalues[(y * w) + x + w];
377 auto yrf = m_yvalues[(y * w) + x + w + 1];
378 auto yrb = m_yvalues[(y * w) + x + 1];
379
380 // calculate midpoint of trapeziod
381 auto xpos = (xlb + xlf + xrf + xrb) / 4;
382 auto ypos = (ylb + ylf + yrf + yrb) / 4;
383
384 // Translate detector shape to origin
385 xlf -= xpos;
386 xrf -= xpos;
387 xrb -= xpos;
388 xlb -= xpos;
389 ylf -= ypos;
390 yrf -= ypos;
391 yrb -= ypos;
392 ylb -= ypos;
393
394 std::shared_ptr<Mantid::Geometry::IObject> shape =
395 ShapeFactory{}.createHexahedralShape(xlb, xlf, xrf, xrb, ylb, ylf, yrf, yrb);
396
397 // Create detector
398 auto detector = new Detector(name, id, shape, parent);
399
400 // Set detector position relative to parent
401 V3D pos(xpos, ypos, 0);
402
403 detector->translate(pos);
404
405 return detector;
406}
407
412 if (m_map)
413 return m_base->m_minDetId;
414 return m_minDetId;
415}
416
417//-------------------------------------------------------------------------------------------------
422 if (m_map)
423 return m_base->m_maxDetId;
424 return m_maxDetId;
425}
426
427std::shared_ptr<const IComponent> StructuredDetector::getComponentByName(const std::string &cname, int nlevels) const {
428 // exact matches
429 if (cname == this->getName())
430 return std::shared_ptr<const IComponent>(this);
431
432 // cache the detector's name as all the other names are longer
433 // The extra ( is because all children of this have that as the next character
434 // and this prevents Bank11 matching Bank 1
435 const std::string MEMBER_NAME = this->getName() + "(";
436
437 // check that the searched for name starts with the detector's
438 // name as they are generated
439 if (cname.substr(0, MEMBER_NAME.length()) != MEMBER_NAME) {
440 return std::shared_ptr<const IComponent>();
441 } else {
442 return CompAssembly::getComponentByName(cname, nlevels);
443 }
444}
445
446//-------------------------------------------------------------------------------------------------
447//-------------------------------------------------------------------------------------------------
448// ------------ IObjComponent methods ----------------
449//-------------------------------------------------------------------------------------------------
450//-------------------------------------------------------------------------------------------------
451
452//-------------------------------------------------------------------------------------------------
454bool StructuredDetector::isValid(const V3D & /*point*/) const {
455 throw Kernel::Exception::NotImplementedError("StructuredDetector::isValid() is not implemented.");
456}
457
459bool StructuredDetector::isOnSide(const V3D & /*point*/) const {
460 throw Kernel::Exception::NotImplementedError("StructuredDetector::isOnSide() is not implemented.");
461}
462
465 throw Kernel::Exception::NotImplementedError("StructuredDetector::interceptSurface() is not implemented.");
466}
467
470double StructuredDetector::solidAngle(const V3D & /*observer*/) const {
471 throw Kernel::Exception::NotImplementedError("StructuredDetector::solidAngle() is not implemented.");
472}
473
476 throw Kernel::Exception::NotImplementedError("StructuredDetector::getPointInObject() is not implemented.");
477}
478
485 if (hasComponentInfo()) {
486 assemblyBox = m_map->componentInfo().boundingBox(index(), &assemblyBox);
487 return;
488 }
489 if (!m_cachedBoundingBox) {
491 // Get all the corners
492 BoundingBox compBox;
493
494 std::shared_ptr<Detector> det = getAtXY(0, 0);
495 det->getBoundingBox(compBox);
496 m_cachedBoundingBox->grow(compBox);
497 det = getAtXY(this->xPixels() - 1, 0);
498 det->getBoundingBox(compBox);
499 m_cachedBoundingBox->grow(compBox);
500 det = getAtXY(this->xPixels() - 1, this->yPixels() - 1);
501 det->getBoundingBox(compBox);
502 m_cachedBoundingBox->grow(compBox);
503 det = getAtXY(0, this->yPixels() - 1);
504 det->getBoundingBox(compBox);
505 m_cachedBoundingBox->grow(compBox);
506 }
507 // Use cached box
508 assemblyBox = *m_cachedBoundingBox;
509}
510
516 if (Handle() == nullptr)
517 return;
518 // Render the ObjComponent and then render the object
519 Handle()->render();
520}
521
526
532 if (Handle() == nullptr)
533 return;
534
535 Handle()->initialize();
536}
537
539const std::shared_ptr<const IObject> StructuredDetector::shape() const {
540 // --- Create a hexahedral shape for your pixels ----
541 auto w = this->xPixels() + 1;
542 auto xlb = m_xvalues[0];
543 auto xlf = m_xvalues[w * m_yPixels];
544 auto xrf = m_xvalues[(w * m_yPixels) + m_xPixels];
545 auto xrb = m_xvalues[w];
546 auto ylb = m_yvalues[0];
547 auto ylf = m_yvalues[(w * m_yPixels)];
548 auto yrf = m_yvalues[(w * m_yPixels) + m_xPixels];
549 auto yrb = m_yvalues[w];
550
551 std::ostringstream xmlShapeStream;
552
553 xmlShapeStream << "<hexahedron id=\"detector-shape\" >"
554 << "<left-back-bottom-point x=\"" << xlb << "\""
555 << " y=\"" << ylb << "\""
556 << " z=\"0\" />"
557 << "<left-front-bottom-point x=\"" << xlf << "\""
558 << " y=\"" << ylf << "\""
559 << " z=\"0\" />"
560 << "<right-front-bottom-point x=\"" << xrf << "\""
561 << " y=\"" << yrf << "\""
562 << " z=\"0\" />"
563 << "<right-back-bottom-point x=\"" << xrb << "\""
564 << " y=\"" << yrb << "\""
565 << " z=\"0\" />"
566 << "<left-back-top-point x=\"" << xlb << "\""
567 << " y=\"" << ylb << "\""
568 << " z=\"0.5\" />"
569 << "<left-front-top-point x=\"" << xlf << "\""
570 << " y=\"" << ylf << "\""
571 << " z=\"0.5\" />"
572 << "<right-front-top-point x=\"" << xrf << "\""
573 << " y=\"" << yrf << "\""
574 << " z=\"0.5\" />"
575 << "<right-back-top-point x=\"" << xrb << "\""
576 << " y=\"" << yrb << "\""
577 << " z=\"0.5\" />"
578 << "</hexahedron>";
579
580 std::string xmlHexahedralShape(xmlShapeStream.str());
581 Geometry::ShapeFactory shapeCreator;
582
583 return shapeCreator.createShape(xmlHexahedralShape);
584}
585
587
588//-------------------------------------------------------------------------------------------------
589//-------------------------------------------------------------------------------------------------
590// ------------ END OF IObjComponent methods ----------------
591//-------------------------------------------------------------------------------------------------
592//-------------------------------------------------------------------------------------------------
593
604std::ostream &operator<<(std::ostream &os, const StructuredDetector &ass) {
605 ass.printSelf(os);
606 os << "************************\n";
607 os << "Number of children :" << ass.nelements() << '\n';
608 ass.printChildren(os);
609 return os;
610}
611
612size_t StructuredDetector::registerContents(class ComponentVisitor &componentVisitor) const {
613 return componentVisitor.registerStructuredBank(*this);
614}
615
616} // namespace Mantid::Geometry
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition: BoundingBox.h:34
void grow(const BoundingBox &other)
Grow the bounding box so that it also encompasses the given box.
Class for Assembly of geometric components.
Definition: CompAssembly.h:31
void printChildren(std::ostream &) const override
Print information about all children.
BoundingBox * m_cachedBoundingBox
A cached bounding box.
Definition: CompAssembly.h:101
int add(IComponent *) override
Add a component to the assembly.
std::shared_ptr< const IComponent > getComponentByName(const std::string &cname, int nlevels=0) const override
Returns a pointer to the first component of assembly encountered with the given name.
std::shared_ptr< IComponent > getChild(const int i) const override
Get a pointer to the ith component within the assembly. Easier to use than.
CompAssembly()
Empty constructor.
int nelements() const override
Return the number of elements in the assembly.
BoundingBox boundingBox(const size_t componentIndex, const BoundingBox *reference=nullptr, const bool excludeMonitors=false) const
Compute the bounding box for the component with componentIndex taking into account all sub components...
ComponentVisitor : Visitor for IComponents.
virtual size_t registerStructuredBank(const ICompAssembly &bank)=0
const ParameterMap * m_map
A pointer to const ParameterMap containing the parameters.
Definition: Component.h:307
size_t index() const
Helper for legacy access mode. Returns the index of the component.
Definition: Component.cpp:297
This class represents a detector - i.e.
Definition: Detector.h:30
void render() const
Render Object or ObjComponent.
void initialize() const
Prepare/Initialize Object/ObjComponent to be rendered.
base class for Geometric IComponent
Definition: IComponent.h:51
virtual void printSelf(std::ostream &) const =0
Prints a text representation of itself.
virtual void setName(const std::string &)=0
Set the IComponent name.
virtual std::string getName() const =0
Get the IComponent name.
Object Component class, this class brings together the physical attributes of the component to the po...
Definition: IObjComponent.h:37
void setGeometryHandler(GeometryHandler *h)
Reset the current geometry handler.
GeometryHandler * Handle() const
Gets the GeometryHandler.
Definition: IObjComponent.h:92
const Geometry::ComponentInfo & componentInfo() const
Only for use by ExperimentInfo. Returns a reference to the ComponentInfo.
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
Definition: ShapeFactory.h:89
static std::shared_ptr< CSGObject > createHexahedralShape(double xlb, double xlf, double xrf, double xrb, double ylb, double ylf, double yrf, double yrb)
Create a hexahedral shape object.
std::shared_ptr< CSGObject > createShape(Poco::XML::Element *pElem)
Creates a geometric object from a DOM-element-node pointing to an element whose child nodes contain t...
StructuredDetector is a type of CompAssembly, an assembly of components.
void createDetectors()
Creates all detector pixels within the StructuredDetector.
std::vector< int > const & getB() const
Returns the blue color channel for detector colors.
Detector * addDetector(CompAssembly *parent, const std::string &name, size_t x, size_t y, detid_t id)
Creates new hexahedral detector pixel at row x column y using the detector vertex values.
void draw() const override
Draws the objcomponent.
std::vector< double > const & getXValues() const
int interceptSurface(Track &track) const override
Checks whether the track given will pass through this Component.
static bool compareName(const std::string &proposedMatch)
Matches name to Structured Detector.
size_t m_xPixels
The number of pixels in the X (horizontal) direction;.
detid_t maxDetectorID()
maximum detector id
int idStepByRow() const
Returns the idStepByRow.
virtual size_t registerContents(class ComponentVisitor &componentVisitor) const override
Register the structured detector for Instrument 2.0 usage.
detid_t m_maxDetId
maximum detector id
std::shared_ptr< Detector > getAtXY(const size_t x, const size_t y) const
Return a pointer to the component in the assembly at the (X,Y) pixel position.
std::vector< int > const & getG() const
Returns the green color channel for detector colors.
void drawObject() const override
Draws the Object.
int idStep() const
Returns the idStep.
detid_t getDetectorIDAtXY(const size_t X, const size_t Y) const
Return the detector ID corresponding to the component in the assembly at the (X,Y) pixel position.
size_t yPixels() const
Returns the number of pixels in the Y direction.
size_t m_yPixels
The number of pixels in the Y (vertical) direction;.
void initDraw() const override
Initializes the ObjComponent for rendering, this function should be called before rendering.
std::vector< int > const & getR() const
Returns the red color channel for detector colors.
const std::shared_ptr< const IObject > shape() const override
Returns the shape of the Object.
std::pair< size_t, size_t > getXYForDetectorID(const detid_t detectorID) const
Given a detector ID, return the X,Y coords into the structured detector.
bool idFillByFirstY() const
Returns the idFillByFirstY.
size_t xPixels() const
Returns the number of pixels in the X direction.
const StructuredDetector * m_base
Pointer to the base RectangularDetector, for parametrized instruments.
void initialize(size_t xPixels, size_t yPixels, std::vector< double > &&x, std::vector< double > &&y, bool isZBeam, detid_t idStart, bool idFillByFirstY, int idStepByRow, int idStep=1)
Create all the detector pixels of this rectangular detector.
int m_idStepByRow
Step size in ID in each row.
int getPointInObject(Kernel::V3D &point) const override
Try to find a point that lies within (or on) the object.
void getBoundingBox(BoundingBox &assemblyBox) const override
Retrieve the cached bounding box.
detid_t idStart() const
Returns the idStart.
bool isOnSide(const Kernel::V3D &point) const override
Does the point given lie on the surface of this object component?
int m_idStep
Step size in ID in each col.
detid_t m_minDetId
minimum detector id
std::shared_ptr< const IComponent > getComponentByName(const std::string &cname, int nlevels=0) const override
Returns a pointer to the first component of assembly encountered with the given name.
bool m_idFillByFirstY
IDs are filled in Y fastest.
bool isValid(const Kernel::V3D &point) const override
Does the point given lie within this object component?
double solidAngle(const Kernel::V3D &observer) const override
Finds the approximate solid angle covered by the component when viewed from the point given.
std::vector< double > const & getYValues() const
const Kernel::Material material() const override
Returns the material of the detector.
detid_t minDetectorID()
minimum detector id
void setColors(const std::vector< int > &r, const std::vector< int > &g, const std::vector< int > &b) const
Sets the colours for detector IDs based on color maps created by instrument actor.
void init()
initialize members to bare defaults
IComponent * clone() const override
Make a clone of the present component.
Defines a track as a start point and a direction.
Definition: Track.h:165
Marks code as not implemented yet.
Definition: Exception.h:138
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
Definition: Material.h:50
Class for 3D vectors.
Definition: V3D.h:34
MANTID_GEOMETRY_DLL std::ostream & operator<<(std::ostream &stream, const PointGroup &self)
Returns a streamed representation of the PointGroup object.
Definition: PointGroup.cpp:312
std::shared_ptr< ICompAssembly > ICompAssembly_sptr
Shared pointer to a ICompAssembly.
Definition: ICompAssembly.h:79
int32_t detid_t
Typedef for a detector ID.
Definition: SpectrumInfo.h:21