ATLAS Offline Software
Loading...
Searching...
No Matches
SiDetElementBoundaryLink_xk.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
6// Implementation file for class InDet::SiDetElementBoundaryLink_xk
8// (c) ATLAS Detector software
11// Version 1.0 21/04/2004 I.Gavrilenko
13
15
19
20#include <array>
21#include <utility>
22
24// Constructor
26
28( const InDetDD::SiDetectorElement*& Si, bool isITk)
29{
30 m_ITkGeometry = isITk;
31 m_detelement = nullptr;
32 m_dR = 0.;
33 const Trk::PlaneSurface* pla = dynamic_cast<const Trk::PlaneSurface*>(& Si->surface());
34 // Code below make sense if a surface exists
35 if(!pla) return;
36 m_detelement = Si;
37
38 double x[4],y[4],z[4];
39 double Ax[3] = {1., 0., 0.};
40 double Ay[3] = {0., 1., 0.};
41
42 // Check if we have annulus bounds as this changes a few calculations below
43 const Trk::AnnulusBounds* annulusBounds = dynamic_cast<const Trk::AnnulusBounds*>(&Si->design().bounds());
44
45 if (annulusBounds) {
46
47 // Radial component of the sensor centre, from (m_R, 0., 0.)
48 // This is used to correct the ITk strip endcap local position which have a local coordinate
49 // system centred on the beam axis, due to their annulus shape.
50 m_dR = (Si->design().sensorCenter())[0];
51
52 // Getting the corners directly from the bounds, as for annulus bounds
53 // the calculation below is not correct
54 auto corners = annulusBounds->corners();
55
56 x[0] = corners[0].first;
57 y[0] = corners[0].second - m_dR;
58 z[0] = 0.;
59
60 x[1] = corners[1].first;
61 y[1] = corners[1].second - m_dR;
62 z[1] = 0.;
63
64 x[2] = corners[2].first;
65 y[2] = corners[2].second - m_dR;
66 z[2] = 0.;
67
68 x[3] = corners[3].first;
69 y[3] = corners[3].second - m_dR;
70 z[3] = 0.;
71
72 // For annuli, don't need to re-evaluate the rotation matrix
73 // as the corners are already provided in the correct frame
74
75 } else {
76
77 // Getting detector element length and widths from design class
78 double Sl = .5*Si->design().length ();
79 double Swmax = .5*Si->design().maxWidth();
80 double Swmin = .5*Si->design().minWidth();
81
82 // Getting phi and eta axis of the detector element
83 // They provide the rotation of the local frame wrt the global frame
84 Amg::Vector3D AF = Si->phiAxis();
85 Amg::Vector3D AE = Si->etaAxis();
86
87 // Module dimensions and rotation terms are used to evaluate the 4 corner points in
88 // a reference frame centered in the center of the module and rotated as phi/eta axis
89 x[0] = AF.x()*Swmax+AE.x()*Sl;
90 y[0] = AF.y()*Swmax+AE.y()*Sl;
91 z[0] = AF.z()*Swmax+AE.z()*Sl;
92
93 x[1] = AF.x()*Swmin-AE.x()*Sl;
94 y[1] = AF.y()*Swmin-AE.y()*Sl;
95 z[1] = AF.z()*Swmin-AE.z()*Sl;
96
97 x[2] =-AF.x()*Swmin-AE.x()*Sl;
98 y[2] =-AF.y()*Swmin-AE.y()*Sl;
99 z[2] =-AF.z()*Swmin-AE.z()*Sl;
100
101 x[3] =-AF.x()*Swmax+AE.x()*Sl;
102 y[3] =-AF.y()*Swmax+AE.y()*Sl;
103 z[3] =-AF.z()*Swmax+AE.z()*Sl;
104
105 const Amg::Transform3D& T = pla->transform();
106 Ax[0] = T(0,0);
107 Ax[1] = T(1,0);
108 Ax[2] = T(2,0);
109
110 Ay[0] = T(0,1);
111 Ay[1] = T(1,1);
112 Ay[2] = T(2,1);
113 }
114
115 // Combine the 4 corners to measure 4 vector bounds.
116 // Before starting, you transform the corner coordinates
117 // to the local frame using the surface transform.
118 // Then you evaluate the vector to the i-th bound where:
119 // m_bound[i][0] and m_bound[i][1] are the unit vector components
120 // along directions loc-x and loc-y representing the i-th bound
121 // m_bound[i][2] is distance to the i-th bound along direction (m_bound[i][0], m_bound[i][1])
122
123 // Corners are combined clockwise:
124 // Representation for planar sensor with
125 // rectangular (left) and trapezoidal (right) bounds:
126 //
127 //
128 // ^ loc-y ^ loc-y
129 // | |
130 // p3 | p0 p3 | p0
131 // ...|... .........|.........
132 // : | : . | .
133 // : | : . | .
134 // --------------------> loc-x -----------------------> loc-x
135 // : | : . | .
136 // : | : . | .
137 // ...|... ...|...
138 // p2 | p1 p2 | p1
139 // | |
140 //
141 // NB: Inner and outer radial bounds are assumed to be
142 // straight lines for annulus surfaces.
143
144 constexpr std::array<std::pair<int, int>, 4> combinations = {
145 {{0, 1}, {1, 2}, {2, 3}, {3, 0}}};
146 for (unsigned int bound = 0; bound < combinations.size(); bound++) {
147
148 // Combining 4 corners (p0, p1), (p1, p2), (p2, p3), (p3, p0)
149 int firstCornerIndex = combinations[bound].first;
150 int secondCornerIndex = combinations[bound].second;
151
152 // Evaluation of 4 corners in local frame as shown above in the drawing
153 double x1 = x[firstCornerIndex]*Ax[0]+y[firstCornerIndex]*Ax[1]+z[firstCornerIndex]*Ax[2];
154 double y1 = x[firstCornerIndex]*Ay[0]+y[firstCornerIndex]*Ay[1]+z[firstCornerIndex]*Ay[2];
155 double x2 = x[secondCornerIndex]*Ax[0]+y[secondCornerIndex]*Ax[1]+z[secondCornerIndex]*Ax[2];
156 double y2 = x[secondCornerIndex]*Ay[0]+y[secondCornerIndex]*Ay[1]+z[secondCornerIndex]*Ay[2];
157
158 // distance between p[firstCornerIndex] and p[secondCornerIndex]
159 double d = (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);
160 // Evaluating direction to bound:
161 // x component of the distance to bound connecting p[firstCornerIndex] and p[secondCornerIndex]
162 double ax =-(y2-y1)*(y1*x2-x1*y2)/d;
163 // y component of the distance to bound connecting p[firstCornerIndex] and p[secondCornerIndex]
164 double ay = (x2-x1)*(y1*x2-x1*y2)/d;
165
166 // distance to the bound
167 m_bound[bound][2] = sqrt(ax*ax+ay*ay);
168 // unit vector components along loc-x and loc-y representing the direction to the bound
169 m_bound[bound][0] = ax/m_bound[bound][2];
170 m_bound[bound][1] = ay/m_bound[bound][2];
171 }
172}
173
175// Detector element intersection test
177
179{
180 const AmgVector(5) & p = Tp.parameters();
181 double x = p[0];
182 double y = p[1]-m_dR;
183
184 const AmgSymMatrix(5) & cov = *Tp.covariance();
185
186 // Evaluating distance (in mm) between local parameters and origin of the local reference frame,
187 // along 4 possible axis directions: positive local x, negative local y, negative local x, positive local y.
188 // The evaluated distance behaves as follows:
189 // - it is negative if the local parameter coordinate is inside the module along the given direction.
190 // - it increases moving towards the boundary, and is 0 at the bound.
191 // - it is positive if outside the module bounds.
192 // The largest positive distance drives the intersection check.
193 //
194 // First evaluating distance along positive x axis (local frame)
196 distance = m_bound[direction][0]*x+m_bound[direction][1]*y-m_bound[direction][2];
197
198 // Then testing other directions (local frame)
199 constexpr std::array<int, 3> otherDirections = {
203
204 for (const auto& testDirection : otherDirections) {
205 double testDistance = m_bound[testDirection][0]*x+m_bound[testDirection][1]*y-m_bound[testDirection][2];
206 if (testDistance>distance) {
207 distance = testDistance;
208 direction = testDirection;
209 }
210 }
211
212 // If distance very big (>20 mm), the intersection is definitely outside the bounds
213 // returning intersection outside detector element
214 if(distance > 20. )
216
217 // Tolerance window from the bounds is evaluated accordingly to the
218 // covariance and a scale factor=100
219 double tolerance = (m_bound[direction][0]*m_bound[direction][0]* cov(0, 0)+
220 m_bound[direction][1]*m_bound[direction][1]* cov(1, 1)+
221 m_bound[direction][0]*m_bound[direction][1]*(cov(0, 1)*2.))*100.;
222
223 if(!m_ITkGeometry){
224
225 // within the tolerance window, returning intersection not inside nor outside detector element
226 if((distance*distance) <= tolerance)
228
229 // if outside the tolerance window and distance is larger than 2 mm
230 // returning intersection outside detector element
231 if(distance > 2.)
233
234 // if inside bounds and far them by more than 2 mm
235 if(distance < -2.) {
236 // if not close to bond gap, returning intersection inside detector element
237 if(!m_detelement->nearBondGap(Tp.localPosition(), 3.*sqrt(cov(1, 1))))
239 }
240 }
241
242 else{
243 // within the tolerance window, returning 0: intersection not inside nor outside detector element
244 // For ITk we use 3 mm range around the bounds + tolerance evaluated using the covariance matrix
245 if(std::abs(distance) <=3. or (distance*distance) <= tolerance)
247 // if outside the tolerance window and distance is positive (which means it is larger than 3 mm)
248 // returning intersection outside detector element
249 else if(distance > 0.)
251 // otherwise it is inside bounds
252 else
254 }
255
256 // in any other case
257 // returning 0: intersection not inside nor outside detector element
259}
#define AmgSymMatrix(dim)
#define AmgVector(rows)
static Double_t Tp(Double_t *t, Double_t *par)
#define y
#define x
#define z
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.
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
Trk::Surface & surface()
Element Surface.
Bounds for a annulus-like, planar Surface.
std::array< std::pair< double, double >, 4 > corners() const
Returns the four corners of the bounds.
Class for a planaer rectangular or trapezoidal surface in the ATLAS detector.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D