ATLAS Offline Software
Loading...
Searching...
No Matches
ActsDetectorElement.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include "GeoModelKernel/throwExcept.h"
8
9// ATHENA
19#include "TrkSurfaces/Surface.h"
22
23// PACKAGE
25// ACTS
26#include "Acts/Definitions/Units.hpp"
27#include "Acts/Geometry/GeometryContext.hpp"
28#include "Acts/Surfaces/AnnulusBounds.hpp"
29#include "Acts/Surfaces/DiscSurface.hpp"
30#include "Acts/Surfaces/LineBounds.hpp"
31#include "Acts/Surfaces/PlaneSurface.hpp"
32#include "Acts/Surfaces/RectangleBounds.hpp"
33#include "Acts/Surfaces/StrawSurface.hpp"
34#include "Acts/Surfaces/TrapezoidBounds.hpp"
35#include "Acts/Visualization/ObjVisualization3D.hpp"
36#include "Acts/Visualization/PlyVisualization3D.hpp"
37
38
39// STL
40#include <mutex>
41#include <variant>
42
43
44using Acts::Surface;
45using Acts::Transform3;
46
47using namespace Acts::UnitLiterals;
48using namespace ActsTrk;
49
50
51constexpr double length_unit = 1_mm;
52
54 GeoVDetectorElement{detElem.getMaterialGeom()},
55 m_idHash(detElem.identifyHash()),
56 m_type{detElem.isPixel() ? DetectorType::Pixel : DetectorType::Sct},
57 m_detElement{&detElem},
59{
60
61
62 auto boundsType = detElem.bounds().type();
63
64 m_thickness = detElem.thickness();
65
66
67 if (boundsType == Trk::SurfaceBounds::Rectangle) {
68
69 const InDetDD::SiDetectorDesign &design = detElem.design();
70 double hlX = design.width() / 2. * length_unit;
71 double hlY = design.length() / 2. * length_unit;
72
73 auto rectangleBounds = std::make_shared<const Acts::RectangleBounds>(hlX, hlY);
74
75 m_bounds = rectangleBounds;
76 m_surface = Acts::Surface::makeShared<Acts::PlaneSurface>(rectangleBounds, *this);
77 m_surface->assignThickness(thickness());
78
79 } else if (boundsType == Trk::SurfaceBounds::Trapezoid) {
80
81 const InDetDD::SiDetectorDesign &design = detElem.design();
82
83 double minHlX = design.minWidth() / 2. * length_unit;
84 double maxHlX = design.maxWidth() / 2. * length_unit;
85 double hlY = design.length() / 2. * length_unit;
86
87 auto trapezoidBounds =
88 std::make_shared<const Acts::TrapezoidBounds>(minHlX, maxHlX, hlY);
89
90 m_bounds = trapezoidBounds;
91
92 m_surface = Acts::Surface::makeShared<Acts::PlaneSurface>(trapezoidBounds, *this);
93 m_surface->assignThickness(thickness());
94
95
96 } else if (boundsType == Trk::SurfaceBounds::Annulus) {
97
98 const InDetDD::SiDetectorDesign &design = detElem.design();
99 const auto *annulus = dynamic_cast<const InDetDD::StripStereoAnnulusDesign *>(&design);
100 if (annulus == nullptr) {
101 throw std::domain_error("ActsDetectorElement got inconsistent surface");
102 }
103
104 double phi = annulus->phiWidth();
105 double phiS = annulus->stereo();
106 double R = annulus->waferCentreR();
107 double maxR = annulus->maxR();
108 double minR = annulus->minR();
109
110 // phiAvg is the bounds-internal local rotation. We don't want one
111 double phiAvg = 0;
112 // phi is the total opening angle, set up symmetric phi bounds
113 double phiMax = phi / 2.;
114 double phiMin = -phiMax;
115
116
117 Amg::Vector2D originStripXYRotated(R * (1 - std::cos(phiS)),
118 R * std::sin(-phiS));
119
120 auto annulusBounds = std::make_shared<Acts::AnnulusBounds>(
121 minR, maxR, phiMin, phiMax, originStripXYRotated, phiAvg);
122 m_bounds = annulusBounds;
123
124 m_surface = Acts::Surface::makeShared<Acts::DiscSurface>(annulusBounds, *this);
125 m_surface->assignThickness(thickness());
126
127 } else {
128 std::cout << boundsType << std::endl;
129 throw std::domain_error("ActsDetectorElement does not support this surface type");
130 }
131}
132
133ActsDetectorElement::ActsDetectorElement(const Acts::Transform3 &trf,
134 const InDetDD::TRT_BaseElement &detElem,
135 const Identifier &id) :
136 GeoVDetectorElement{detElem.getMaterialGeom()},
137 m_idHash(detElem.identifyHash()),
139 m_detElement{&detElem},
140 m_trtTrf{std::make_unique<Amg::Transform3D>(trf)},
142{
143
144
145 // we know this is a straw
146 double length = detElem.strawLength() * 0.5 * length_unit;
147
148 // we need to find the radius
149 auto ecElem = dynamic_cast<const InDetDD::TRT_EndcapElement *>(&detElem);
150 auto brlElem = dynamic_cast<const InDetDD::TRT_BarrelElement *>(&detElem);
151 double innerTubeRadius{0.};
152 if (ecElem) {
153 innerTubeRadius = ecElem->getDescriptor()->innerTubeRadius() * length_unit;
154 } else {
155 if (brlElem) {
156 innerTubeRadius =
157 brlElem->getDescriptor()->innerTubeRadius() * length_unit;
158 } else {
159 THROW_EXCEPTION("Cannot get tube radius for element in ActsDetectorElement c'tor");
160 }
161 }
162
163 auto lineBounds =
164 std::make_shared<const Acts::LineBounds>(innerTubeRadius, length);
165 m_bounds = lineBounds;
166
167 m_surface = Acts::Surface::makeShared<Acts::StrawSurface>(lineBounds, *this);
168 m_surface->assignThickness(thickness());
169}
170
172 GeoVDetectorElement{detElem.getMaterialGeom()},
173 m_idHash(detElem.identifyHash()),
175 m_detElement{&detElem},
176 m_thickness{detElem.thickness()},
178{
179
180 auto boundsType = detElem.bounds().type();
181
182 if (boundsType == Trk::SurfaceBounds::Rectangle) {
183
184 const InDetDD::HGTD_ModuleDesign &design = detElem.design();
185 double hlX = design.width() / 2. * length_unit;
186 double hlY = design.length() / 2. * length_unit;
187
188 auto rectangleBounds =
189 std::make_shared<const Acts::RectangleBounds>(hlX, hlY);
190
191 m_bounds = rectangleBounds;
192
193 m_surface = Acts::Surface::makeShared<Acts::PlaneSurface>(rectangleBounds, *this);
194 m_surface->assignThickness(thickness());
195
196 } else {
197 throw std::domain_error(
198 "ActsDetectorElement: the surface type of HGTD is not does not Rectangle, it is wrong");
199 }
200}
201
203
204 GeoAlignmentStore* geoModelStore = store ? store->geoModelAlignment.get() : nullptr;
205 Amg::Transform3D l2g{Amg::Transform3D::Identity()};
206 switch (m_type) {
207 case DetectorType::Hgtd:{
208 l2g= m_detElement->getMaterialGeom()->getAbsoluteTransform(geoModelStore);
209 break;
210 } case DetectorType::Trt: {
211 l2g = (*m_trtTrf);
212 break;
213 }
215 default: {
216 const auto& detElem = static_cast<const InDetDD::SiDetectorElement&>(*m_detElement);
217 const InDetDD::SiDetectorDesign&design = detElem.design();
218 const Trk::SurfaceBounds::BoundsType boundsType = detElem.bounds().type();
219
220 // extra shift for split row modules
221 Amg::Transform3D extraTransform{Amg::CLHEPTransformToEigen(detElem.recoToHitTransform())};
222 if (boundsType == Trk::SurfaceBounds::Rectangle &&
223 typeid(design) == typeid(InDetDD::StripBoxDesign) ) {
224 extraTransform = design.moduleShift() * extraTransform;
225 } else if (boundsType == Trk::SurfaceBounds::Annulus) {
226 // need to rotate pi/2 to reproduce ABXY orientation, phiS so that phi=0
227 // is center and symmetric
228 const double phiShift = M_PI_2 - static_cast<const InDetDD::StripStereoAnnulusDesign&>(design).stereo();
229
230 const Amg::Vector2D origin2D = static_cast<const Acts::AnnulusBounds&>(m_surface->bounds()).moduleOrigin();
231 const Amg::Translation3D transl{origin2D.x(), origin2D.y(), 0};
232 const Amg::Transform3D originTrf{transl * Amg::getRotateZ3D(-phiShift)};
233 extraTransform = extraTransform * originTrf.inverse();
234 }
235 l2g = m_detElement->getMaterialGeom()->getAbsoluteTransform(geoModelStore) * extraTransform;
236 }
237 };
238 // need to make sure translation has correct units
239 l2g.translation() *= 1.0 / CLHEP::mm * length_unit;
240
241 return l2g;
242
243}
246 return IdentityHelper(static_cast<const InDetDD::SiDetectorElement *>(m_detElement));
247 } else {
248 throw std::domain_error("Cannot get IdentityHelper for TRT element");
249 }
250}
251
252const Acts::Transform3 &ActsDetectorElement::localToGlobalTransform(const Acts::GeometryContext &anygctx) const {
253 return m_trfCache.localToGlobalTransform(anygctx);
254}
255
257 if (store.detType != detectorType()) return 0;
258 m_trfCache.getTransform(&store);
259 return 1;
260}
261
262const Acts::Transform3 & ActsDetectorElement::getDefaultTransform() const {
263 return m_trfCache.getTransform(nullptr);
264}
265
266const Acts::Surface &ActsDetectorElement::surface() const {
267 return (*m_surface);
268}
269
271 return (*m_surface);
272}
273
275 if (const auto *detElem =
276 dynamic_cast<const InDetDD::SiDetectorElement *>(m_detElement);
277 detElem != nullptr) {
278 return detElem->surface();
279 } else {
280 throw std::domain_error("Cannot get surface for TRT element");
281 }
282}
283
285
289
290const GeoVDetectorElement *
constexpr double length_unit
Scalar phi() const
phi method
Eigen::Affine3d Transform3D
double length(const pvec &v)
ActsDetectorElement(const InDetDD::SiDetectorElement &detElem)
std::unique_ptr< const Amg::Transform3D > m_trtTrf
const Acts::Transform3 & getDefaultTransform() const
Returns default transform.
ActsTrk::DetectorType DetectorType
const Trk::Surface & atlasSurface() const
Return a shared pointer on the ATLAS surface associated with this identifier,.
double m_thickness
Thickness of this detector element.
ActsTrk::TransformCacheDetEle< ActsDetectorElement > m_trfCache
DetectorType detectorType() const override final
Detector type.
std::shared_ptr< const Acts::SurfaceBounds > m_bounds
Boundaries of the detector element.
Identifier identify() const override final
Identifier.
IdentifierHash identifyHash() const
Identifier hash.
IdentityHelper identityHelper() const
std::shared_ptr< Acts::Surface > m_surface
Corresponding Surface.
const GeoVDetectorElement * m_detElement
Detector element as variant.
double thickness() const
Returns the thickness of the module.
const GeoVDetectorElement * upstreamDetectorElement() const
Returns the underllying GeoModel detectorelement that this one is based on.
virtual const Acts::Surface & surface() const final override
Return surface associated with this identifier, which should come from the.
virtual unsigned int storeAlignedTransforms(const ActsTrk::DetectorAlignStore &alignStore) const override
Caches the aligned transformation in the provided store. Returns the number of cached elements.
Amg::Transform3D localToGlobal(const ActsTrk::DetectorAlignStore *store) const
virtual const Acts::Transform3 & localToGlobalTransform(const Acts::GeometryContext &gctx) const final override
Ensure that the extensions for the Vector3D are properly loaded.
virtual const Amg::Transform3D moduleShift() const
virtual double maxWidth() const =0
Method to calculate maximum width of a module.
virtual double minWidth() const =0
Method to calculate minimum width of a module.
virtual double length() const =0
Method to calculate length of a module.
virtual double width() const =0
Method to calculate average width of a module.
Class to hold geometrical description of an HGTD detector element.
const HGTD_ModuleDesign & design() const override final
access to the local description:
Class used to describe the design of a module (diode segmentation and readout scheme)
virtual double width() const
Method to calculate average width of a module.
virtual double length() const
Method to calculate length of a module.
Base class for the detector design classes for Pixel and SCT.
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
virtual const Trk::SurfaceBounds & bounds() const override final
Return the boundaries of the element.
Extended TRT_BaseElement to describe a TRT readout element, this is a planar layer with n ( order of ...
Virtual base class of TRT readout elements.
virtual const double & strawLength() const =0
Active straw length.
Extended class of a TRT_BaseElement to describe a readout elment in the endcap.
BoundsType
This enumerator simplifies the persistency, by saving a dynamic_cast to happen.
Abstract Base Class for tracking surfaces.
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
@ Pixel
Inner detector legacy.
@ Trt
Maybe the Sct / Pixel for Itk become seperate entries?
Definition of ATLAS Math & Geometry primitives (Amg)
Amg::Transform3D CLHEPTransformToEigen(const HepGeom::Transform3D &CLHEPtransf)
Converts a CLHEP-based HepGeom::Transform3D into an Eigen Amg::Transform3D.
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Translation< double, 3 > Translation3D
STL namespace.
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10