Mantid
Loading...
Searching...
No Matches
GridDetector.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 +
20#include "MantidKernel/Matrix.h"
21#include <algorithm>
22#include <boost/regex.hpp>
23#include <memory>
24#include <ostream>
25#include <stdexcept>
26#include <utility>
27
28namespace Mantid::Geometry {
29
30using Kernel::Matrix;
31using Kernel::V3D;
32
38 : CompAssembly(base, map), IObjComponent(nullptr), m_gridBase(base), m_minDetId(0), m_maxDetId(0) {
39 init();
41}
42
52GridDetector::GridDetector(const std::string &n, IComponent *reference)
53 : CompAssembly(n, reference), IObjComponent(nullptr), m_gridBase(nullptr), m_minDetId(0), m_maxDetId(0) {
54 init();
55 this->setName(n);
57}
58
59bool GridDetector::compareName(const std::string &proposedMatch) {
60 static const boost::regex exp("grid_?detector", boost::regex::icase);
61 return boost::regex_match(proposedMatch, exp);
62}
63
66 m_xsize = m_ysize = m_zsize = 0;
68 m_xstep = m_ystep = m_zstep = 0;
70 m_idstart = 0;
71 m_idfillbyfirst_y = false;
72 m_idstepbyrow = 0;
73 m_idstep = 0;
74}
75
80GridDetector *GridDetector::clone() const { return new GridDetector(*this); }
81
82bool GridDetector::inBoundsXYZ(const int x, const int y, const int z) const {
83 if ((xpixels() <= 0) || (ypixels() <= 0))
84 throw std::runtime_error("GridDetector::inBoundsXYZ: invalid X or Y "
85 "width set in the object.");
86 if ((x < 0) || (x >= xpixels()))
87 return false;
88 if ((y < 0) || (y >= ypixels()))
89 return false;
90 if (zpixels() > 0) {
91 if ((z < 0) || (z >= zpixels()))
92 return false;
93 }
94 return true;
95}
96
97//-------------------------------------------------------------------------------------------------
109std::shared_ptr<Detector> GridDetector::getAtXYZ(const int x, const int y, const int z) const {
110 if ((xpixels() <= 0) || (ypixels() <= 0))
111 throw std::runtime_error("GridDetector::getAtXY: invalid X or Y "
112 "width set in the object.");
113 if ((x < 0) || (x >= xpixels()))
114 throw std::runtime_error("GridDetector::getAtXYZ: x specified is out of range.");
115 if ((y < 0) || (y >= ypixels()))
116 throw std::runtime_error("GridDetector::getAtXYZ: y specified is out of range.");
117 if (zpixels() > 0) {
118 if ((z < 0) || (z >= zpixels()))
119 throw std::runtime_error("GridDetector::getAtXYZ: z specified is out of range.");
120 }
121
122 // Find the index and return that.
123 std::shared_ptr<ICompAssembly> xCol;
124 // Get to layer
125 if (this->zpixels() > 0) {
126 auto zLayer = std::dynamic_pointer_cast<ICompAssembly>(this->getChild(z));
127 if (!zLayer)
128 throw std::runtime_error("GridDetector::getAtXYZ: z specified is out of range.");
129
130 xCol = std::dynamic_pointer_cast<ICompAssembly>(zLayer->getChild(x));
131 } else
132 xCol = std::dynamic_pointer_cast<ICompAssembly>(this->getChild(x));
133
134 if (!xCol)
135 throw std::runtime_error("GridDetector::getAtXYZ: x specified is out of range.");
136 return std::dynamic_pointer_cast<Detector>(xCol->getChild(y));
137}
138
139namespace {
140int const &orderXYZ(char const order, int const &x, int const &y, int const &z) {
141 switch (order) {
142 case 'x':
143 return x;
144 case 'y':
145 return y;
146 case 'z':
147 return z;
148 default:
149 throw std::runtime_error("Not a dimensional label: " + std::to_string(order));
150 }
151}
152
153int const &pixelsXYZ(char const order, GridDetector const *const me) {
154 switch (order) {
155 case 'x':
156 return me->xpixels();
157 case 'y':
158 return me->ypixels();
159 case 'z':
160 return me->zpixels();
161 default:
162 throw std::runtime_error(std::string("Not a dimensional label: ") + order);
163 }
164}
165} // namespace
166
167//-------------------------------------------------------------------------------------------------
178detid_t GridDetector::getDetectorIDAtXYZ(const int x, const int y, const int z) const {
179 if (!inBoundsXYZ(x, y, z))
180 throw std::out_of_range("GridDetector::getDetectorIDAtXYZ: pixel indices are out of range.");
181
182 auto order = idFillOrder();
183
184 int const &first = orderXYZ(order[0], x, y, z);
185 int const &second = orderXYZ(order[1], x, y, z);
186 int const &third = orderXYZ(order[2], x, y, z);
187
188 return idstart() + first * idstep() + second * idstepbyrow() + third * (pixelsXYZ(order[1], this) * idstepbyrow());
189}
190
191namespace {
192std::tuple<int, int, int> getXYZFillFirstZ(const GridDetector *me, int col, int id) {
193 if (me->idFillOrder()[1] == 'y') {
194 int row = (id / me->idstepbyrow()) % me->ypixels();
195 auto layer = (id / me->idstepbyrow()) / me->ypixels();
196 return std::tuple<int, int, int>(layer, row, col);
197 } else {
198 int row = (id / me->idstepbyrow()) % me->xpixels();
199 auto layer = (id / me->idstepbyrow()) / me->xpixels();
200 return std::tuple<int, int, int>(row, layer, col);
201 }
202}
203
204std::tuple<int, int, int> getXYZFillFirstY(const GridDetector *me, int col, int id) {
205 if (me->idFillOrder()[1] == 'z') {
206 int row = (id / me->idstepbyrow()) % me->zpixels();
207 auto layer = (id / me->idstepbyrow()) / me->zpixels();
208 return std::tuple<int, int, int>(layer, col, row);
209 } else {
210 int row = (id / me->idstepbyrow()) % me->xpixels();
211 auto layer = (id / me->idstepbyrow()) / me->xpixels();
212 return std::tuple<int, int, int>(row, col, layer);
213 }
214}
215
216std::tuple<int, int, int> getXYZFillFirstX(const GridDetector *me, int col, int id) {
217 if (me->idFillOrder()[1] == 'y') {
218 int row = (id / me->idstepbyrow()) % me->ypixels();
219 auto layer = (id / me->idstepbyrow()) / me->ypixels();
220 return std::tuple<int, int, int>(col, row, layer);
221 } else {
222 int row = (id / me->idstepbyrow()) % me->zpixels();
223 auto layer = (id / me->idstepbyrow()) / me->zpixels();
224 return std::tuple<int, int, int>(col, layer, row);
225 }
226}
227} // end namespace
228
229//-------------------------------------------------------------------------------------------------
235std::tuple<int, int, int> GridDetector::getXYZForDetectorID(const detid_t detectorID) const {
236 const GridDetector *me = this;
237 if (isParametrized())
238 me = this->m_gridBase;
239
240 int id = detectorID - me->m_idstart;
241 if ((me->m_idstepbyrow == 0) || (me->m_idstep == 0))
242 return std::tuple<int, int, int>(-1, -1, -1);
243 int col = (id % me->m_idstepbyrow) / me->m_idstep;
244
245 if (me->m_idFillOrder[0] == 'z')
246 return getXYZFillFirstZ(me, col, id);
247 else if (me->m_idFillOrder[0] == 'y')
248 return getXYZFillFirstY(me, col, id);
249 else
250 return getXYZFillFirstX(me, col, id);
251}
252
253//-------------------------------------------------------------------------------------------------
256int const &GridDetector::xpixels() const {
257 if (isParametrized())
258 return m_gridBase->xpixels();
259 else
260 return this->m_xpixels;
261}
262
263//-------------------------------------------------------------------------------------------------
266int const &GridDetector::ypixels() const {
267 if (isParametrized())
268 return m_gridBase->ypixels();
269 else
270 return this->m_ypixels;
271}
272
273//-------------------------------------------------------------------------------------------------
276int const &GridDetector::zpixels() const {
277 if (isParametrized())
278 return m_gridBase->zpixels();
279 else
280 return this->m_zpixels;
281}
282
283//-------------------------------------------------------------------------------------------------
285double GridDetector::xstep() const {
286 if (isParametrized()) {
287 double scaling = 1.0;
288 if (m_map->contains(m_gridBase, "scalex"))
289 scaling = m_map->get(m_gridBase, "scalex")->value<double>();
290 return m_gridBase->xstep() * scaling;
291 } else
292 return this->m_xstep;
293}
294
295//-------------------------------------------------------------------------------------------------
297double GridDetector::ystep() const {
298 if (isParametrized()) {
299 double scaling = 1.0;
300 if (m_map->contains(m_gridBase, "scaley"))
301 scaling = m_map->get(m_gridBase, "scaley")->value<double>();
302 return m_gridBase->ystep() * scaling;
303 } else
304 return this->m_ystep;
305}
306
307//-------------------------------------------------------------------------------------------------
309double GridDetector::zstep() const {
310 if (isParametrized()) {
311 double scaling = 1.0;
312 if (m_map->contains(m_gridBase, "scalez"))
313 scaling = m_map->get(m_gridBase, "scalez")->value<double>();
314 return m_gridBase->zstep() * scaling;
315 } else
316 return this->m_zstep;
317}
318
319//-------------------------------------------------------------------------------------------------
321double GridDetector::xstart() const {
322 if (isParametrized()) {
323 double scaling = 1.0;
324 if (m_map->contains(m_gridBase, "scalex"))
325 scaling = m_map->get(m_gridBase, "scalex")->value<double>();
326 return m_gridBase->xstart() * scaling;
327 } else
328 return this->m_xstart;
329}
330
331//-------------------------------------------------------------------------------------------------
333double GridDetector::ystart() const {
334 if (isParametrized()) {
335 double scaling = 1.0;
336 if (m_map->contains(m_gridBase, "scaley"))
337 scaling = m_map->get(m_gridBase, "scaley")->value<double>();
338 return m_gridBase->ystart() * scaling;
339 } else
340 return this->m_ystart;
341}
342
343//-------------------------------------------------------------------------------------------------
345double GridDetector::zstart() const {
346 if (isParametrized()) {
347 double scaling = 1.0;
348 if (m_map->contains(m_gridBase, "scalez"))
349 scaling = m_map->get(m_gridBase, "scalez")->value<double>();
350 return m_gridBase->zstart() * scaling;
351 } else
352 return this->m_zstart;
353}
354
355//-------------------------------------------------------------------------------------------------
357double GridDetector::xsize() const {
358 if (isParametrized()) {
359 double scaling = 1.0;
360 if (m_map->contains(m_gridBase, "scalex"))
361 scaling = m_map->get(m_gridBase, "scalex")->value<double>();
362 return m_gridBase->xsize() * scaling;
363 } else
364 return this->m_xsize;
365}
366
367//-------------------------------------------------------------------------------------------------
369double GridDetector::ysize() const {
370 if (isParametrized()) {
371 double scaling = 1.0;
372 if (m_map->contains(m_gridBase, "scaley"))
373 scaling = m_map->get(m_gridBase, "scaley")->value<double>();
374 return m_gridBase->ysize() * scaling;
375 } else
376 return this->m_ysize;
377}
378
379//-------------------------------------------------------------------------------------------------
381double GridDetector::zsize() const {
382 if (isParametrized()) {
383 double scaling = 1.0;
384 if (m_map->contains(m_gridBase, "scalez"))
385 scaling = m_map->get(m_gridBase, "scalez")->value<double>();
386 return m_gridBase->zsize() * scaling;
387 } else
388 return this->m_zsize;
389}
390
391//-------------------------------------------------------------------------------------------------
393int const &GridDetector::idstart() const {
394 if (isParametrized())
395 return m_gridBase->idstart();
396 else
397 return this->m_idstart;
398}
399
400//-------------------------------------------------------------------------------------------------
402bool const &GridDetector::idfillbyfirst_y() const {
403 if (isParametrized())
404 return m_gridBase->idfillbyfirst_y();
405 else
406 return this->m_idfillbyfirst_y;
407}
408
410std::array<char, 3UL> const &GridDetector::idFillOrder() const {
411 if (isParametrized())
412 return m_gridBase->idFillOrder();
413 else
414 return this->m_idFillOrder;
415}
416
417//-------------------------------------------------------------------------------------------------
419int const &GridDetector::idstepbyrow() const {
420 if (isParametrized())
421 return m_gridBase->idstepbyrow();
422 else
423 return this->m_idstepbyrow;
424}
425
426//-------------------------------------------------------------------------------------------------
428int const &GridDetector::idstep() const {
429 if (isParametrized())
430 return m_gridBase->idstep();
431 else
432 return this->m_idstep;
433}
434
435//-------------------------------------------------------------------------------------------------
445V3D GridDetector::getPosAtXYZ(int x, int y, int z) const {
446 if (!inBoundsXYZ(x, y, z))
447 throw std::out_of_range("GridDetector::getPosAtXYZ: pixel indices are out of range.");
448 V3D relPos = getRelativePosAtXYZ(x, y, z);
449 this->getRotation().rotate(relPos);
450 return this->getPos() + relPos;
451}
452
453//-------------------------------------------------------------------------------------------------
464 if (isParametrized()) {
465 double scalex = 1.0;
466 if (m_map->contains(m_gridBase, "scalex"))
467 scalex = m_map->get(m_gridBase, "scalex")->value<double>();
468 double scaley = 1.0;
469 if (m_map->contains(m_gridBase, "scaley"))
470 scaley = m_map->get(m_gridBase, "scaley")->value<double>();
471 double scalez = 1.0;
472 if (m_map->contains(m_gridBase, "scalez"))
473 scalez = m_map->get(m_gridBase, "scalez")->value<double>();
474 return m_gridBase->getRelativePosAtXYZ(x, y, z) * V3D(scalex, scaley, scalez);
475 } else
476 return V3D(m_xstart + m_xstep * x, m_ystart + m_ystep * y, m_zstart + m_zstep * z);
477}
478
479void GridDetector::createLayer(const std::string &name, CompAssembly *parent, int iz, int &minDetID, int &maxDetID) {
480 const double z = m_zstart + iz * m_zstep;
481 const std::string z_pixel_str = (m_zpixels > 0) ? "," + std::to_string(iz) + ")" : ")";
482 const std::string z_layer_str = (m_zpixels > 0) ? name + "(z=" + std::to_string(iz) + ",x=" : name + "(x=";
483 for (int ix = 0; ix < m_xpixels; ++ix) {
484 const std::string x_pixel_str = name + "(" + std::to_string(ix) + ",";
485 const std::string name_layer = z_layer_str + std::to_string(ix) + ")";
486
487 // Create an ICompAssembly for each x-column
488 auto *xColumn = new CompAssembly(name_layer, parent);
489
490 const double x = m_xstart + ix * m_xstep;
491 for (int iy = 0; iy < m_ypixels; ++iy) {
492 // Make the name
493 const std::string name_pixel = x_pixel_str + std::to_string(iy) + z_pixel_str;
494
495 // Calculate its id and set it.
496 const auto id = this->getDetectorIDAtXYZ(ix, iy, iz);
497
498 // minimum grid detector id
499 if (id < minDetID) {
500 minDetID = id;
501 }
502 // maximum grid detector id
503 if (id > maxDetID) {
504 maxDetID = id;
505 }
506 // Create the detector from the given id & shape and with xColumn as the parent
507 auto *detector =
508 new GridDetectorPixel(name_pixel, id, m_shape, xColumn, this, size_t(ix), size_t(iy), size_t(iz));
509
510 const double y = m_ystart + iy * m_ystep;
511 // Translate (relative to parent). This gives the un-parametrized position
512 detector->translate(x, y, z);
513
514 // Add it to the x-column
515 xColumn->add(detector);
516 }
517 }
518}
519
520namespace {
521bool checkValidOrderString(std::array<char, 3UL> const &order) {
522 return std::all_of(order.cbegin(), order.cend(), [](char const &c) { return (c >= 'x') && (c <= 'z'); });
523}
524} // end namespace
525
527 // Some safety checks
528 if (!checkValidOrderString(m_idFillOrder))
529 throw std::invalid_argument(
530 "GridDetector::initialize(): order string should only comprise exactly 3 letters x, y, and z in any order.");
531 if (m_xpixels <= 0)
532 throw std::invalid_argument("GridDetector::initialize(): xpixels should be > 0");
533 if (m_ypixels <= 0)
534 throw std::invalid_argument("GridDetector::initialize(): ypixels should be > 0");
535}
536
537void GridDetector::initializeValues(std::shared_ptr<IObject> shape, int xpixels, double xstart, double xstep,
538 int ypixels, double ystart, double ystep, int zpixels, double zstart, double zstep,
539 int idstart, const std::string &idFillOrder, int idstepbyrow, int idstep) {
540
550 m_xstep = xstep;
551 m_ystep = ystep;
552 m_zstep = zstep;
553 m_shape = std::move(shape);
554
558 m_idfillbyfirst_y = idFillOrder[0] == 'y';
560 m_idFillOrder = std::array<char, 3>{idFillOrder[0], idFillOrder[1], idFillOrder[2]};
565
567}
568
569//-------------------------------------------------------------------------------------------------
603void GridDetector::initialize(std::shared_ptr<IObject> shape, int xpixels, double xstart, double xstep, int ypixels,
604 double ystart, double ystep, int zpixels, double zstart, double zstep, int idstart,
605 const std::string &idFillOrder, int idstepbyrow, int idstep) {
606
607 if (isParametrized())
608 throw std::runtime_error("GridDetector::initialize() called for a parametrized GridDetector");
609
612
613 std::string name = this->getName();
614 int minDetId = idstart, maxDetId = idstart;
615 // Loop through all the pixels
616 if (m_zpixels > 0) {
617 for (int iz = 0; iz < m_zpixels; ++iz) {
618 // Create an ICompAssembly for each z-layer
619 std::ostringstream oss_layer;
620 oss_layer << name << "(z=" << iz << ")";
621 createLayer(name, new CompAssembly(oss_layer.str(), this), iz, minDetId, maxDetId);
622 }
623 } else
624 createLayer(name, this, 0, minDetId, maxDetId);
625
626 m_minDetId = minDetId;
627 m_maxDetId = maxDetId;
628}
629
630//-------------------------------------------------------------------------------------------------
635 if (isParametrized())
636 return m_gridBase->minDetectorID();
637 return m_minDetId;
638}
639
640//-------------------------------------------------------------------------------------------------
645 if (isParametrized())
646 return m_gridBase->maxDetectorID();
647 return m_maxDetId;
648}
649
650//-------------------------------------------------------------------------------------------------
652std::shared_ptr<const IComponent> GridDetector::getComponentByName(const std::string &cname, int nlevels) const {
653 // exact matches
654 if (cname == this->getName())
655 return std::shared_ptr<const IComponent>(this);
656
657 // cache the detector's name as all the other names are longer
658 // The extra ( is because all children of this have that as the next character
659 // and this prevents Bank11 matching Bank 1
660 const std::string MEMBER_NAME = this->getName() + "(";
661
662 // check that the searched for name starts with the detector's
663 // name as they are generated
664 if (cname.substr(0, MEMBER_NAME.length()) != MEMBER_NAME) {
665 return std::shared_ptr<const IComponent>();
666 } else {
667 return CompAssembly::getComponentByName(cname, nlevels);
668 }
669}
670
671//------------------------------------------------------------------------------------------------
682 std::deque<IComponent_const_sptr> & /*searchQueue*/) const {
684 V3D const basePoint = getRelativePosAtXYZ(0, 0, 0);
685
687 V3D const vertical = getRelativePosAtXYZ(0, ypixels() - 1, 0) - basePoint;
688
690 V3D horizontal = getRelativePosAtXYZ(xpixels() - 1, 0, 0) - basePoint;
691
692 // The beam direction
693 V3D const beam = testRay.direction() * (-1.0);
694
695 // From: http://en.wikipedia.org/wiki/Line-plane_intersection (taken on May 4,
696 // 2011),
697 // We build a matrix to solve the linear equation:
698 Matrix<double> mat(3, 3);
699 mat.setColumn(0, beam);
700 mat.setColumn(1, horizontal);
701 mat.setColumn(2, vertical);
702 mat.Invert();
703
704 // Multiply by the inverted matrix to find t,u,v
705 V3D const tuv = mat * (testRay.startPoint() - basePoint);
706 // std::cout << tuv << "\n";
707
708 // Intersection point
709 V3D const intersec = beam * (tuv[0] * -1.0);
710
711 // t = coordinate along the line
712 // u,v = coordinates along horizontal, vertical
713 // (and correct for it being between 0, xpixels-1). The +0.5 is because the
714 // base point is at the CENTER of pixel 0,0.
715 double u = (double(xpixels() - 1) * tuv[1] + 0.5);
716 double v = (double(ypixels() - 1) * tuv[2] + 0.5);
717
718 // std::cout << u << ", " << v << "\n";
719
720 // In indices
721 auto xIndex = int(u);
722 auto yIndex = int(v);
723
724 // Out of range?
725 if (xIndex < 0)
726 return;
727 if (yIndex < 0)
728 return;
729 if (xIndex >= xpixels())
730 return;
731 if (yIndex >= ypixels())
732 return;
733
734 // All pixels share the same pixel shape stored on the detector.
735 // The parametrized form delegates to the base detector's shape.
736 std::shared_ptr<IObject> const &pixelShape = isParametrized() ? m_gridBase->m_shape : m_shape;
737
738 auto comp = getAtXYZ(xIndex, yIndex, 0);
739 testRay.addLink(intersec, intersec, 0.0, *pixelShape, comp->getComponentID());
740}
741
742//-------------------------------------------------------------------------------------------------
743//-------------------------------------------------------------------------------------------------
744// ------------ IObjComponent methods ----------------
745//-------------------------------------------------------------------------------------------------
746//-------------------------------------------------------------------------------------------------
747
748//-------------------------------------------------------------------------------------------------
750bool GridDetector::isValid(const V3D & /*point*/) const {
751 throw Kernel::Exception::NotImplementedError("GridDetector::isValid() is not implemented.");
752}
753
754//-------------------------------------------------------------------------------------------------
756bool GridDetector::isOnSide(const V3D & /*point*/) const {
757 throw Kernel::Exception::NotImplementedError("GridDetector::isOnSide() is not implemented.");
758}
759
760//-------------------------------------------------------------------------------------------------
762int GridDetector::interceptSurface(Track & /*track*/) const {
763 throw Kernel::Exception::NotImplementedError("GridDetector::interceptSurface() is not implemented.");
764}
765
766//-------------------------------------------------------------------------------------------------
769double GridDetector::solidAngle(const Geometry::SolidAngleParams & /*params*/) const {
770 throw Kernel::Exception::NotImplementedError("GridDetector::solidAngle() is not implemented.");
771}
772
773//-------------------------------------------------------------------------------------------------
775int GridDetector::getPointInObject(V3D & /*point*/) const {
776 throw Kernel::Exception::NotImplementedError("GridDetector::getPointInObject() is not implemented.");
777}
778
779void GridDetector::getBoundingBoxAtXYZ(int const x, int const y, int const z, BoundingBox &box) const {
780 // Compute the pixel bounding box analytically, replicating ObjComponent::getBoundingBox
781 // without needing an actual child Detector object. Each pixel shares the same shape
782 // (m_shape) and inherits the GridDetector's rotation with no additional per-pixel rotation.
783
784 // For a parametrized detector the shape lives on the base.
785 std::shared_ptr<IObject> const &pixelShape = isParametrized() ? m_gridBase->m_shape : m_shape;
786 if (!pixelShape || !pixelShape->hasValidShape()) {
787 box = BoundingBox();
788 return;
789 }
790
791 const BoundingBox &shapeBox = pixelShape->getBoundingBox();
792 if (shapeBox.isNull()) {
793 box = BoundingBox();
794 return;
795 }
796
797 // 1. Copy the shape's axis-aligned bounding box in the local (pixel) frame.
798 box = BoundingBox(shapeBox);
799
800 // 1a. For parametrized detectors, scale the shape extents by scalex/scaley/scalez
801 // so the per-pixel box matches the scaled pixel size (consistent with getPosAtXYZ).
802 if (isParametrized()) {
803 double scalex = 1.0, scaley = 1.0, scalez = 1.0;
804 if (m_map->contains(m_gridBase, "scalex"))
805 scalex = m_map->get(m_gridBase, "scalex")->value<double>();
806 if (m_map->contains(m_gridBase, "scaley"))
807 scaley = m_map->get(m_gridBase, "scaley")->value<double>();
808 if (m_map->contains(m_gridBase, "scalez"))
809 scalez = m_map->get(m_gridBase, "scalez")->value<double>();
810 box.xMin() *= scalex;
811 box.xMax() *= scalex;
812 box.yMin() *= scaley;
813 box.yMax() *= scaley;
814 box.zMin() *= scalez;
815 box.zMax() *= scalez;
816 }
817
818 // 2. Rotate: pixels have the same orientation as the parent GridDetector; there
819 // is no additional per-pixel rotation, so we apply the detector's own rotation.
820 this->getRotation().rotateBB(box.xMin(), box.yMin(), box.zMin(), box.xMax(), box.yMax(), box.zMax());
821
822 // 3. Translate to the pixel's absolute position in the instrument frame.
823 Kernel::V3D const pixelPos = getPosAtXYZ(x, y, z);
824 box.xMin() += pixelPos.X();
825 box.xMax() += pixelPos.X();
826 box.yMin() += pixelPos.Y();
827 box.yMax() += pixelPos.Y();
828 box.zMin() += pixelPos.Z();
829 box.zMax() += pixelPos.Z();
830}
831
832//-------------------------------------------------------------------------------------------------
839 if (isParametrized()) {
840 if (hasComponentInfo()) {
841 assemblyBox = m_map->componentInfo().boundingBox(index(), &assemblyBox);
842 return;
843 }
844 }
845 BoundingBox bb;
846 BoundingBox compBox;
847 getBoundingBoxAtXYZ(0, 0, 0, compBox);
848 bb.grow(compBox);
849 getBoundingBoxAtXYZ(this->xpixels() - 1, 0, 0, compBox);
850 bb.grow(compBox);
851 getBoundingBoxAtXYZ(this->xpixels() - 1, this->ypixels() - 1, 0, compBox);
852 bb.grow(compBox);
853 getBoundingBoxAtXYZ(0, this->ypixels() - 1, 0, compBox);
854 bb.grow(compBox);
855 getBoundingBoxAtXYZ(0, 0, this->zpixels() - 1, compBox);
856 bb.grow(compBox);
857 getBoundingBoxAtXYZ(this->xpixels() - 1, 0, this->zpixels() - 1, compBox);
858 bb.grow(compBox);
859 getBoundingBoxAtXYZ(this->xpixels() - 1, this->ypixels() - 1, this->zpixels() - 1, compBox);
860 bb.grow(compBox);
861 getBoundingBoxAtXYZ(0, this->ypixels() - 1, this->zpixels() - 1, compBox);
862 bb.grow(compBox);
863
864 assemblyBox = bb;
865}
866
871void GridDetector::draw() const {
872 if (Handle() == nullptr)
873 return;
874 Handle()->render();
875}
876
881
887 if (Handle() == nullptr)
888 return;
889 Handle()->initialize();
890}
891
892//-------------------------------------------------------------------------------------------------
894const std::shared_ptr<const IObject> GridDetector::shape() const {
895 // --- Create a cuboid shape for your pixels ----
896 double szX = xpixels();
897 double szY = ypixels();
898 double szZ = zpixels() == 0 ? 0.5 : zpixels();
899 std::ostringstream xmlShapeStream;
900 xmlShapeStream << " <cuboid id=\"detector-shape\"> "
901 << "<left-front-bottom-point x=\"" << szX << "\" y=\"" << -szY << "\" z=\"" << -szZ << "\" /> "
902 << "<left-front-top-point x=\"" << szX << "\" y=\"" << -szY << "\" z=\"" << szZ << "\" /> "
903 << "<left-back-bottom-point x=\"" << -szX << "\" y=\"" << -szY << "\" z=\"" << -szZ << "\" /> "
904 << "<right-front-bottom-point x=\"" << szX << "\" y=\"" << szY << "\" z=\"" << -szZ << "\" /> "
905 << "</cuboid>";
906
907 std::string xmlCuboidShape(xmlShapeStream.str());
908 Geometry::ShapeFactory shapeCreator;
909 std::shared_ptr<Geometry::IObject> cuboidShape = shapeCreator.createShape(xmlCuboidShape);
910
911 return cuboidShape;
912}
913
915
916size_t GridDetector::registerContents(ComponentVisitor &componentVisitor) const {
917 return componentVisitor.registerGridBank(*this);
918}
919
920//-------------------------------------------------------------------------------------------------
921//-------------------------------------------------------------------------------------------------
922// ------------ END OF IObjComponent methods ----------------
923//-------------------------------------------------------------------------------------------------
924//-------------------------------------------------------------------------------------------------
925
936std::ostream &operator<<(std::ostream &os, const GridDetector &ass) {
937 ass.printSelf(os);
938 os << "************************\n";
939 os << "Number of children :" << ass.nelements() << '\n';
940 ass.printChildren(os);
941 return os;
942}
943
944} // namespace Mantid::Geometry
std::string name
Definition Run.cpp:60
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition BoundingBox.h:33
double xMax() const
Return the maximum value of X.
Definition BoundingBox.h:79
double zMin() const
Return the minimum value of Z.
Definition BoundingBox.h:85
bool isNull() const
Is this a default constructed box?
double zMax() const
Return the maximum value of Z.
Definition BoundingBox.h:87
double yMax() const
Return the maximum value of Y.
Definition BoundingBox.h:83
double xMin() const
Return the minimum value of X.
Definition BoundingBox.h:77
double yMin() const
Return the minimum value of Y.
Definition BoundingBox.h:81
void grow(const BoundingBox &other)
Grow the bounding box so that it also encompasses the given box.
Class for Assembly of geometric components.
void printChildren(std::ostream &) const override
Print information about all children.
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.
Kernel::V3D getPos() const override
Gets the absolute position of the Parametrized CompAssembly This attempts to read the cached position...
Kernel::Quat getRotation() const override
Gets the absolute position of the Parametrized CompAssembly This attempts to read the cached position...
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 registerGridBank(const ICompAssembly &bank)=0
const ParameterMap * m_map
A pointer to const ParameterMap containing the parameters.
Definition Component.h:316
size_t index() const
Helper for legacy access mode. Returns the index of the component.
void render() const
Render Object or ObjComponent.
void initialize() const
Prepare/Initialize Object/ObjComponent to be rendered.
GridDetector is a type of CompAssembly, an assembly of components.
static bool compareName(const std::string &proposedMatch)
Matches name to Structured Detector.
double m_zstart
Z position of the 0-th pixel.
bool m_idfillbyfirst_y
IDs are filled in Y fastest.
double ystart() const
Returns the start position in the Y direction.
std::tuple< int, int, int > getXYZForDetectorID(const detid_t detectorID) const
Given a detector ID, return the X,Y,Z coords into the grid detector.
const std::shared_ptr< const IObject > shape() const override
Returns the shape of the Object.
GridDetector * clone() const override
Make a clone of the present component.
std::array< char, 3UL > const & idFillOrder() const
returns dimensions of filling in order
std::shared_ptr< Detector > getAtXYZ(const int x, const int y, const int z) const
Return a pointer to the component in the assembly at the (X,Y) pixel position.
int m_xpixels
The number of pixels in the X (horizontal) direction.
bool isParametrized() const override
Returns true if the Component is parametrized (has a parameter map)
double m_ysize
Size in Y of the detector.
std::shared_ptr< IObject > m_shape
Pointer to the shape of the pixels in this detector array.
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.
int m_ypixels
The number of pixels in the Y (vertical) direction.
void initializeValues(std::shared_ptr< IObject > shape, int xpixels, double xstart, double xstep, int ypixels, double ystart, double ystep, int zpixels, double zstart, double zstep, int idstart, const std::string &idFillOrder, int idstepbyrow, int idstep)
double ysize() const
Size in Y of the detector.
double m_ystart
Y position of the 0-th pixel.
int m_idstep
Step size in ID in each col.
double m_zstep
Step size in the Z direction of the detector.
detid_t const & minDetectorID() const
minimum detector id
int const & ypixels() const
Returns the number of pixels in the Y direction.
Kernel::V3D getPosAtXYZ(int const x, int const y, int const z) const
Returns the position of the center of the pixel at x,y, relative to the center of the GridDetector,...
double xsize() const
Size in X of the detector.
void draw() const override
Draws the objcomponent.
void initialize(std::shared_ptr< IObject > shape, int xpixels, double xstart, double xstep, int ypixels, double ystart, double ystep, int zpixels, double zstart, double zstep, int idstart, const std::string &idFillOrder, int idstepbyrow, int idstep=1)
Create all the detector pixels of this grid detector.
void getBoundingBox(BoundingBox &assemblyBox) const override
Retrieve the cached bounding box.
detid_t m_minDetId
minimum detector id
double m_ystep
Step size in the Y direction of detector.
bool const & idfillbyfirst_y() const
returns if IDs are filled along y direction first
void initDraw() const override
Initializes the ObjComponent for rendering, this function should be called before rendering.
double m_xsize
Size in X of the detector.
double ystep() const
Returns the step size in the Y direction.
double xstep() const
Returns the step size in the X direction.
void init()
initialize members to bare defaults
bool isValid(const Kernel::V3D &point) const override
Does the point given lie within this object component?
int interceptSurface(Track &track) const override
Checks whether the track given will pass through this Component.
bool isOnSide(const Kernel::V3D &point) const override
Does the point given lie on the surface of this object component?
GridDetector(const std::string &name, IComponent *reference=nullptr)
Constructor with a name and parent reference.
const GridDetector * m_gridBase
Pointer to the base GridDetector, for parametrized instruments.
int const & xpixels() const
Returns the number of pixels in the X direction.
double m_xstart
X position of the 0-th pixel.
const Kernel::Material material() const override
Returns the material of the detector.
int const & idstepbyrow() const
Returns the idstepbyrow.
void createLayer(const std::string &name, CompAssembly *parent, int iz, int &minDetID, int &maxDetID)
void testIntersectionWithChildren(Track &testRay, std::deque< IComponent_const_sptr > &searchQueue) const override
Test the intersection of the ray with the children of the component assembly, for InstrumentRayTracer...
std::array< char, 3UL > m_idFillOrder
The order in which to fill IDs.
double m_zsize
Size in Z of the detector.
int const & zpixels() const
Returns the number of pixels in the Z direction.
double xstart() const
Returns the start position in the X direction.
detid_t const & maxDetectorID() const
maximum detector id
detid_t getDetectorIDAtXYZ(const int x, const int y, const int z) const
Return the detector ID corresponding to the component in the assembly at the (X,Y) pixel position.
virtual size_t registerContents(class ComponentVisitor &componentVisitor) const override
double zstart() const
Returns the start position in the Z direction.
double solidAngle(const Geometry::SolidAngleParams &params) const override
Finds the approximate solid angle covered by the component when viewed from the point given.
double zsize() const
Size in Z of the detector.
double m_xstep
Step size in the X direction of detector.
void drawObject() const override
Draws the Object.
int m_idstepbyrow
Step size in ID in each row.
int const & idstart() const
Returns the idstart.
int m_zpixels
The number of pixels in the Z (usually beam) direction.
int getPointInObject(Kernel::V3D &point) const override
Try to find a point that lies within (or on) the object.
double zstep() const
Returns the step size in the Z direction.
void getBoundingBoxAtXYZ(int const x, int const y, int const z, BoundingBox &box) const
bool inBoundsXYZ(const int x, const int y, const int z) const
int const & idstep() const
Returns the idstep.
Kernel::V3D getRelativePosAtXYZ(int const x, int const y, int const z) const
Returns the position of the center of the pixel at x,y, relative to the center of the GridDetector,...
detid_t m_maxDetId
maximum detector id
base class for Geometric IComponent
Definition IComponent.h:53
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...
void setGeometryHandler(GeometryHandler *h)
Reset the current geometry handler.
GeometryHandler * Handle() const
Gets the GeometryHandler.
bool contains(const IComponent *comp, const std::string &name, const std::string &type="") const
Does the named parameter exist for the given component and type (std::string version)
std::shared_ptr< Parameter > get(const IComponent *comp, const std::string &name, const std::string &type="") const
Get a parameter with a given name and type (std::string version)
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.
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...
Defines a track as a start point and a direction.
Definition Track.h:165
const Kernel::V3D & startPoint() const
Returns the starting point.
Definition Track.h:191
int addLink(const Kernel::V3D &firstPoint, const Kernel::V3D &secondPoint, const double distanceAlongTrack, const IObject &obj, const ComponentID compID=nullptr)
Adds a link to the track.
Definition Track.cpp:152
const Kernel::V3D & direction() const
Returns the direction as a unit vector.
Definition Track.h:193
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
Numerical Matrix class.
Definition Matrix.h:42
T Invert()
LU inversion routine.
Definition Matrix.cpp:924
void setColumn(const size_t nCol, const std::vector< T > &newCol)
Definition Matrix.cpp:675
void rotate(V3D &) const
Rotate a vector.
Definition Quat.cpp:397
void rotateBB(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) const
Taking two points defining a cuboid bounding box (xmin,ymin,zmin) and.
Definition Quat.cpp:670
Class for 3D vectors.
Definition V3D.h:34
constexpr double X() const noexcept
Get x.
Definition V3D.h:238
constexpr double Y() const noexcept
Get y.
Definition V3D.h:239
constexpr double Z() const noexcept
Get z.
Definition V3D.h:240
MANTID_GEOMETRY_DLL std::ostream & operator<<(std::ostream &stream, const PointGroup &self)
Returns a streamed representation of the PointGroup object.
int32_t detid_t
Typedef for a detector ID.
adjust instrument component position and orientation
: detector size scale at y-direction
std::string to_string(const wide_integer< Bits, Signed > &n)