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
53const ActsDetectorElement* getActsDetectorElement(const Acts::Surface& surf) {
54 if (!surf.isAlignable()) {
55 return nullptr;
56 }
57 const auto* placement = dynamic_cast<const ISurfacePlacement*>(surf.surfacePlacement());
58 if(!placement) {
59 return nullptr;
60 }
61 return dynamic_cast<const ActsDetectorElement*>(placement->detectorElement());
62}
63
64
66 GeoVDetectorElement{detElem.getMaterialGeom()},
67 m_idHash(detElem.identifyHash()),
68 m_type{detElem.isPixel() ? DetectorType::Pixel : DetectorType::Sct},
69 m_detElement{&detElem},
71{
72
73
74 auto boundsType = detElem.bounds().type();
75
76 m_thickness = detElem.thickness();
77
78
79 if (boundsType == Trk::SurfaceBounds::Rectangle) {
80
81 const InDetDD::SiDetectorDesign &design = detElem.design();
82 double hlX = design.width() / 2. * length_unit;
83 double hlY = design.length() / 2. * length_unit;
84
85 auto rectangleBounds = std::make_shared<Acts::RectangleBounds>(hlX, hlY);
86
87 m_bounds = rectangleBounds;
89 m_surfHolder->surface().assignThickness(thickness());
90
91 } else if (boundsType == Trk::SurfaceBounds::Trapezoid) {
92
93 const InDetDD::SiDetectorDesign &design = detElem.design();
94
95 double minHlX = design.minWidth() / 2. * length_unit;
96 double maxHlX = design.maxWidth() / 2. * length_unit;
97 double hlY = design.length() / 2. * length_unit;
98
99 auto trapezoidBounds = std::make_shared<Acts::TrapezoidBounds>(minHlX, maxHlX, hlY);
100
101 m_bounds = trapezoidBounds;
102
104 m_surfHolder->surface().assignThickness(thickness());
105
106
107 } else if (boundsType == Trk::SurfaceBounds::Annulus) {
108
109 const InDetDD::SiDetectorDesign &design = detElem.design();
110 const auto *annulus = dynamic_cast<const InDetDD::StripStereoAnnulusDesign *>(&design);
111 if (annulus == nullptr) {
112 throw std::domain_error("ActsDetectorElement got inconsistent surface");
113 }
114
115 double phi = annulus->phiWidth();
116 double phiS = annulus->stereo();
117 double R = annulus->waferCentreR();
118 double maxR = annulus->maxR();
119 double minR = annulus->minR();
120
121 // phiAvg is the bounds-internal local rotation. We don't want one
122 double phiAvg = 0;
123 // phi is the total opening angle, set up symmetric phi bounds
124 double phiMax = phi / 2.;
125 double phiMin = -phiMax;
126
127
128 Amg::Vector2D originStripXYRotated(R * (1 - std::cos(phiS)),
129 R * std::sin(-phiS));
130
131 auto annulusBounds = std::make_shared<Acts::AnnulusBounds>(minR, maxR,
132 phiMin, phiMax,
133 originStripXYRotated, phiAvg);
134 m_bounds = annulusBounds;
135
137 m_surfHolder->surface().assignThickness(thickness());
138
139 } else {
140 std::cout << boundsType << std::endl;
141 throw std::domain_error("ActsDetectorElement does not support this surface type");
142 }
143}
144
145ActsDetectorElement::ActsDetectorElement(const Acts::Transform3 &trf,
146 const InDetDD::TRT_BaseElement &detElem,
147 const Identifier &id) :
148 GeoVDetectorElement{detElem.getMaterialGeom()},
149 m_idHash(detElem.identifyHash()),
151 m_detElement{&detElem},
152 m_trtTrf{std::make_unique<Amg::Transform3D>(trf)},
154{
155
156
157 // we know this is a straw
158 double length = detElem.strawLength() * 0.5 * length_unit;
159
160 // we need to find the radius
161 auto ecElem = dynamic_cast<const InDetDD::TRT_EndcapElement *>(&detElem);
162 auto brlElem = dynamic_cast<const InDetDD::TRT_BarrelElement *>(&detElem);
163 double innerTubeRadius{0.};
164 if (ecElem) {
165 innerTubeRadius = ecElem->getDescriptor()->innerTubeRadius() * length_unit;
166 } else {
167 if (brlElem) {
168 innerTubeRadius =
169 brlElem->getDescriptor()->innerTubeRadius() * length_unit;
170 } else {
171 THROW_EXCEPTION("Cannot get tube radius for element in ActsDetectorElement c'tor");
172 }
173 }
174
175 auto lineBounds = std::make_shared<Acts::LineBounds>(innerTubeRadius, length);
176 m_bounds = lineBounds;
177
179 m_surfHolder->surface().assignThickness(thickness());
180}
181
183 GeoVDetectorElement{detElem.getMaterialGeom()},
184 m_idHash(detElem.identifyHash()),
186 m_detElement{&detElem},
187 m_thickness{detElem.thickness()},
189{
190
191 auto boundsType = detElem.bounds().type();
192
193 if (boundsType == Trk::SurfaceBounds::Rectangle) {
194
195 const InDetDD::HGTD_ModuleDesign &design = detElem.design();
196 double hlX = design.width() / 2. * length_unit;
197 double hlY = design.length() / 2. * length_unit;
198
199 auto rectangleBounds = std::make_shared<Acts::RectangleBounds>(hlX, hlY);
200
201 m_bounds = rectangleBounds;
202
204 m_surfHolder->surface().assignThickness(thickness());
205
206 } else {
207 throw std::domain_error(
208 "ActsDetectorElement: the surface type of HGTD is not does not Rectangle, it is wrong");
209 }
210}
211
213
214 GeoAlignmentStore* geoModelStore = store ? store->geoModelAlignment.get() : nullptr;
215 Amg::Transform3D l2g{Amg::Transform3D::Identity()};
216 switch (m_type) {
217 case DetectorType::Hgtd:{
218 l2g= m_detElement->getMaterialGeom()->getAbsoluteTransform(geoModelStore);
219 break;
220 } case DetectorType::Trt: {
221 l2g = (*m_trtTrf);
222 break;
223 }
225 default: {
226 const auto& detElem = static_cast<const InDetDD::SiDetectorElement&>(*m_detElement);
227 const InDetDD::SiDetectorDesign&design = detElem.design();
228 const Trk::SurfaceBounds::BoundsType boundsType = detElem.bounds().type();
229
230 // extra shift for split row modules
231 Amg::Transform3D extraTransform{Amg::CLHEPTransformToEigen(detElem.recoToHitTransform())};
232 if (boundsType == Trk::SurfaceBounds::Rectangle &&
233 typeid(design) == typeid(InDetDD::StripBoxDesign) ) {
234 extraTransform = design.moduleShift() * extraTransform;
235 } else if (boundsType == Trk::SurfaceBounds::Annulus) {
236 // need to rotate pi/2 to reproduce ABXY orientation, phiS so that phi=0
237 // is center and symmetric
238 const double phiShift = M_PI_2 - static_cast<const InDetDD::StripStereoAnnulusDesign&>(design).stereo();
239
240 const Amg::Vector2D origin2D = static_cast<const Acts::AnnulusBounds&>(surface().bounds()).moduleOrigin();
241 const Amg::Translation3D transl{origin2D.x(), origin2D.y(), 0};
242 const Amg::Transform3D originTrf{transl * Amg::getRotateZ3D(-phiShift)};
243 extraTransform = extraTransform * originTrf.inverse();
244 }
245 l2g = m_detElement->getMaterialGeom()->getAbsoluteTransform(geoModelStore) * extraTransform;
246 }
247 };
248 // need to make sure translation has correct units
249 l2g.translation() *= 1.0 / CLHEP::mm * length_unit;
250
251 return l2g;
252
253}
258 } else {
259 throw std::domain_error(std::format("Cannot get IdentityHelper for {:} element" ,detectorType()));
260 }
261}
262
263
264
266 return m_trfCache.getTransform(gctx);
267}
268const Acts::Transform3& ActsDetectorElement::localToGlobalTransform(const Acts::GeometryContext &anygctx) const {
269 return m_trfCache.getTransform(anygctx);
270}
272 return m_trfCache.getTransform(store);
273}
274
276 return m_trfCache.storeTransform(store);
277}
278
279const Acts::Transform3 & ActsDetectorElement::getDefaultTransform() const {
280 return m_trfCache.getTransform(nullptr);
281}
282
283const Acts::Surface &ActsDetectorElement::surface() const {
284 return m_surfHolder->surface();
285}
286
288 return m_surfHolder->surface();
289}
290
292 if (const auto *detElem =
294 detElem != nullptr) {
295 return detElem->surface();
296 } else {
297 throw std::domain_error(std::format("Cannot get surface for {:} element" , detectorType()));
298 }
299}
300
302
306
307const GeoVDetectorElement *
constexpr double length_unit
const ActsDetectorElement * getActsDetectorElement(const Acts::Surface &surf)
Attempts to retrieve the ActsDetectorElement associated to the passed ActsSurface.
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 Acts::Transform3 & localToGlobalTransform(const Acts::GeometryContext &tgContext) const
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.
const Acts::Surface & surface() const
Return surface associated with this identifier, which should come from the.
DetectorType detectorType() const override final
Detector type.
ActsTrk::ReadoutSurfacePositioning< ActsDetectorElement > m_trfCache
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
virtual unsigned int storeAlignedTransforms(ActsTrk::DetectorAlignStore &alignStore) const override
Caches the aligned transformation in the provided store.
std::shared_ptr< ActsTrk::SurfacePlacement > m_surfHolder
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.
Amg::Transform3D localToGlobal(const ActsTrk::DetectorAlignStore *store) const
Extension of the interface of the Acts::SurfacePlacementBase for ATLAS.
static std::shared_ptr< SurfacePlacement > makeShared(IReadoutSurfacePositioning &transformCache, std::shared_ptr< Bounds_t > &&bounds)
Factory method to create a SurfacePlacement together with an Acts::Surface.
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):
Class to hold geometrical description of a solid state detector element.
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.
Definition Surface.h:79
The AlignStoreProviderAlg loads the rigid alignment corrections and pipes them through the readout ge...
@ Pixel
Inner detector legacy.
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)
Rotate the coordinate system by an angle around the 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