ATLAS Offline Software
Loading...
Searching...
No Matches
PixelDistortionData.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "CLHEP/Units/SystemOfUnits.h"
7#include "CxxUtils/restrict.h"
8
9#include "cmath"
10namespace {
11
12//constexpr binomial
13//copied over from TMath but in constxpr
14//fashion
15constexpr double Binomial(int n, int k) {
16
17 if (n < 0 || k < 0 || n < k) {
18 return std::numeric_limits<double>::signaling_NaN();
19 }
20 if (k == 0 || n == k) {
21 return 1;
22 }
23
24 int k1 = std::min(k, n - k);
25 int k2 = n - k1;
26 double fact = k2 + 1;
27 for (double i = k1; i > 1.; --i) {
28 fact *= (k2 + i) / i;
29 }
30 return fact;
31}
32
33constexpr int PolyDegree = 20;
34constexpr int PolyNCoeff = PolyDegree + 1;
35
36constexpr std::array<double, PolyNCoeff> BinomialCache() {
37 constexpr double b0 = Binomial(20, 0);
38 constexpr double b1 = Binomial(20, 1);
39 constexpr double b2 = Binomial(20, 2);
40 constexpr double b3 = Binomial(20, 3);
41 constexpr double b4 = Binomial(20, 4);
42 constexpr double b5 = Binomial(20, 5);
43 constexpr double b6 = Binomial(20, 6);
44 constexpr double b7 = Binomial(20, 7);
45 constexpr double b8 = Binomial(20, 8);
46 constexpr double b9 = Binomial(20, 9);
47 constexpr double b10 = Binomial(20, 10);
48
49 std::array<double, PolyNCoeff> res = {b0, b1, b2, b3, b4, b5, b6,
50 b7, b8, b9, b10, b9, b8, b7,
51 b6, b5, b4, b3, b2, b1, b0};
52
53 return res;
54}
55
56// We just have a static const array in the anonymous
57// as cache
58constexpr std::array<double, PolyNCoeff> s_binomialCache = BinomialCache();
59
60template <int N>
61double bernstein_grundpolynom(const double t, const int i) {
62 static_assert(s_binomialCache.size() > N,
63 " Binomial cache must be larger than N");
64
65 return s_binomialCache[i] * std::pow(t, i) * std::pow(1. - t, N - i);
66}
67
68double bernstein_bezier(const double u, const double v, const float *P) {
69 double r = 0.;
70 //So here we calculate the 21+21 polynomial values we need
71 //for the inputs u , v for 0....n each (m==n)
72 std::array<double,PolyNCoeff> bernstein_grundpolynomU{};
73 std::array<double,PolyNCoeff> bernstein_grundpolynomV{};
74 for (int i = 0; i < PolyNCoeff; ++i) {
75 bernstein_grundpolynomU[i] = bernstein_grundpolynom<PolyDegree>(u, i);
76 bernstein_grundpolynomV[i] = bernstein_grundpolynom<PolyDegree>(v, i);
77 }
78
79 for (int i = 0; i < PolyNCoeff; ++i) {
80
81 //the one we passed u and 0 ....n
82 const double bernstein_grundpolynom_i = bernstein_grundpolynomU[i];
83
84 for (int j = 0; j < PolyNCoeff; ++j) {
85
86 const int k = (i * (PolyDegree + 1)) + j;
87 if (P[k] < -998.9){
88 continue;
89 }
90
91 //the one we passed v and 0 ....n
92 const double bernstein_grundpolynom_j = bernstein_grundpolynomV[j];
93 r += bernstein_grundpolynom_i * bernstein_grundpolynom_j * P[k];
94 }
95 }
96 return r;
97}
98} // namespace
99
100std::vector<float> PixelDistortionData::getDistortionMap(uint32_t hashID) const {
101 int distosize;
102 if (m_version < 2) distosize = 3;
103 else distosize = 441;
104
105 auto itr = m_distortionMap.find(hashID);
106 if (itr!=m_distortionMap.end()) {
107 return itr->second;
108 }
109 std::vector<float> map(distosize, 0.0);
110 return map;
111}
112
113unsigned long long PixelDistortionData::getId(uint32_t hashID) const {
114 auto search = m_ids.find(hashID);
115 if (search != m_ids.end()) return search->second;
116
117 return 0;
118}
119
120Amg::Vector2D PixelDistortionData::correction(uint32_t hashID, const Amg::Vector2D & locpos, const Amg::Vector3D & direction) const {
121 double localphi = locpos[0];
122 double localeta = locpos[1];
123 const Amg::Vector2D nullCorrection(0.0,0.0);
124 const unsigned long long ull_id = getId(hashID);
125
126 // No corrections available for this module
127 if (ull_id == 0 && m_version > 1) { return nullCorrection; }
128
129 // This is needed to avoid rounding errors if the z component of the
130 // direction vector is too small.
131 if (std::fabs(direction.z())<1.*CLHEP::micrometer) { return nullCorrection; }
132
133 // If a particle has a too shallow trajectory with respect to the
134 // module direction, it is likely to be a secondary particle and no
135 // shift should be applied.
136 double invtanphi = direction.x()/direction.z();
137 double invtaneta = direction.y()/direction.z();
138 if (std::sqrt(invtanphi*invtanphi+invtaneta*invtaneta)>100.0) { return nullCorrection; }
139
140 double localZ = 0;
141 std::vector<float> map = getDistortionMap(hashID);
142
143 // If old database versions, the corrections are from the pixel survey, otherwise corrections are from
144 // insitu shape measurements.
145 if (m_version < 2) {
146 localZ = getSurveyZ(localeta, localphi, map.data());
147 } else if (isOldParam(ull_id)) {
148 localZ = getSurveyZ(localeta, localphi, map.data());
149 } else {
150 float modEtaSize, modPhiSize;
151
152 // set module sizes in millimetre
153 if (ull_id >= 0x200000000000000 && ull_id <= 0x20d980000000000) {
154 if (isIBL3D(ull_id)) {
155 modEtaSize = 19.75 * CLHEP::millimeter;
156 modPhiSize = 16.75 * CLHEP::millimeter;
157 } else {
158 modEtaSize = 40.4 * CLHEP::millimeter;
159 modPhiSize = 16.8 * CLHEP::millimeter;
160 }
161 } else {
162 modEtaSize = 60.2 * CLHEP::millimeter;
163 modPhiSize = 16.44 * CLHEP::millimeter;
164 }
165
166 localZ = getInSituZ(localeta, modEtaSize, localphi, modPhiSize, map.data());
167 }
168
169 double localetaCor = -localZ * invtaneta;
170 double localphiCor = -localZ * invtanphi;
171
172 // In earlies code version there was a bug in the sign of the correction.
173 // In MC this was not seen as reco just corrects back what was done in digitization.
174 // In order to maintain backward compatibilty in older MC we need to reproduce this wrong behaviour.
175 if (getVersion()==0) { localphiCor = -localphiCor; }
176
177 return Amg::Vector2D(localphiCor, localetaCor);
178}
179
180Amg::Vector2D PixelDistortionData::correctReconstruction(uint32_t hashID, const Amg::Vector2D & locpos, const Amg::Vector3D & direction) const {
181 Amg::Vector2D newlocpos(locpos);
182 newlocpos += correction(hashID, locpos, direction);
183 return newlocpos;
184}
185
186Amg::Vector2D PixelDistortionData::correctSimulation(uint32_t hashID, const Amg::Vector2D & locpos, const Amg::Vector3D & direction) const {
187 Amg::Vector2D newlocpos(locpos);
188 newlocpos -= correction(hashID, locpos, direction);
189 return newlocpos;
190}
191
192double PixelDistortionData::getInSituZ(const double localeta, const double eta_size, const double localphi, const double phi_size, const float *disto)
193{
194 double etaHalfRangeBB = eta_size * 10. / 21.;
195 double phiHalfRangeBB = phi_size * 10. / 21.;
196 double etaRangeBB = eta_size * 20. / 21.;
197 double phiRangeBB = phi_size * 20. / 21.;
198 double eta, phi;
199
200 // map positions on interval [- edge, 1 + edge]
201 // edge is the part outside of the Bezier-Bernstein range
202 if (std::abs(localeta) - etaHalfRangeBB > 0) {
203 if (localeta < 0)
204 eta = (localeta + etaHalfRangeBB) / etaRangeBB;
205 else
206 eta = 1. + (localeta - etaHalfRangeBB) / etaRangeBB;
207 } else {
208 eta = localeta / etaRangeBB + 0.5;
209 }
210 if (std::abs(localphi) - phiHalfRangeBB > 0) {
211 if (localphi < 0)
212 phi = (localphi + phiHalfRangeBB) / phiRangeBB;
213 else
214 phi = 1. + (localphi - phiHalfRangeBB) / phiRangeBB;
215 } else {
216 phi = localphi / phiRangeBB + 0.5;
217 }
218 return bernstein_bezier(eta, phi, disto);
219}
220
221double PixelDistortionData::getSurveyZ(const double localeta, const double localphi, const float *disto)
222{
223 const double xFE = 22.0 * CLHEP::millimeter; // Distance between the 2 Front-End line, where bows have been measured
224 const double yFE = 60.8 * CLHEP::millimeter; // Length of the active surface of each module
225
226 double data0 = disto[0] / CLHEP::meter; // curvature is in m-1
227 double data1 = disto[1] / CLHEP::meter; // curvature is in m-1
228 double data2 = std::tan(0.5 * disto[2] * CLHEP::degree); // twist angle in degree
229
230 double twist1 = -data2;
231 double twist2 = data2;
232 double b1 = std::sqrt((1. + twist1*twist1) * (1. + twist1*twist1) * (1. + twist1*twist1));
233 double b2 = std::sqrt((1. + twist2*twist2) * (1. + twist2*twist2) * (1. + twist2*twist2));
234 double z1 = localeta * twist1 - 0.5 * b1 * localeta*localeta * data1;
235 double z2 = localeta * twist2 - 0.5 * b2 * localeta*localeta * data0;
236 double zoff1 = (b1 * yFE*yFE * data1) / 24.;
237 double zoff2 = (b2 * yFE*yFE * data0) / 24.;
238 z1 = z1 + zoff1;
239 z2 = z2 + zoff2;
240
241 return z1 + ((z2 - z1) / xFE) * (localphi + xFE / 2.);
242}
243
244bool PixelDistortionData::isOldParam(const unsigned long long ull_id)
245{
246 // Only pixel modules can have the old parametrisation
247 if (ull_id < 0x240000000000000) return false;
248
249 // For now: no new parametrisation for Pixel
250 return true;
251}
252
253bool PixelDistortionData::isIBL3D(const unsigned long long ull_id)
254{
255 // Stave 1
256 if (ull_id >= 0x200000000000000 && ull_id <= 0x200180000000000) return true;
257 if (ull_id >= 0x200800000000000 && ull_id <= 0x200980000000000) return true;
258
259 // Stave 2
260 if (ull_id >= 0x201000000000000 && ull_id <= 0x201180000000000) return true;
261 if (ull_id >= 0x201800000000000 && ull_id <= 0x201980000000000) return true;
262
263 // Stave 3
264 if (ull_id >= 0x202000000000000 && ull_id <= 0x202180000000000) return true;
265 if (ull_id >= 0x202800000000000 && ull_id <= 0x202980000000000) return true;
266
267 // Stave 4
268 if (ull_id >= 0x203000000000000 && ull_id <= 0x203180000000000) return true;
269 if (ull_id >= 0x203800000000000 && ull_id <= 0x203980000000000) return true;
270
271 // Stave 5
272 if (ull_id >= 0x204000000000000 && ull_id <= 0x204180000000000) return true;
273 if (ull_id >= 0x204800000000000 && ull_id <= 0x204980000000000) return true;
274
275 // Stave 6
276 if (ull_id >= 0x205000000000000 && ull_id <= 0x205180000000000) return true;
277 if (ull_id >= 0x205800000000000 && ull_id <= 0x205980000000000) return true;
278
279 // Stave 7
280 if (ull_id >= 0x206000000000000 && ull_id <= 0x206180000000000) return true;
281 if (ull_id >= 0x206800000000000 && ull_id <= 0x206980000000000) return true;
282
283 // Stave 8
284 if (ull_id >= 0x207000000000000 && ull_id <= 0x207180000000000) return true;
285 if (ull_id >= 0x207800000000000 && ull_id <= 0x207980000000000) return true;
286
287 // Stave 9
288 if (ull_id >= 0x208000000000000 && ull_id <= 0x208180000000000) return true;
289 if (ull_id >= 0x208800000000000 && ull_id <= 0x208980000000000) return true;
290
291 // Stave 10
292 if (ull_id >= 0x209000000000000 && ull_id <= 0x209180000000000) return true;
293 if (ull_id >= 0x209800000000000 && ull_id <= 0x209980000000000) return true;
294
295 // Stave 11
296 if (ull_id >= 0x20a000000000000 && ull_id <= 0x20a180000000000) return true;
297 if (ull_id >= 0x20a800000000000 && ull_id <= 0x20a980000000000) return true;
298
299 // Stave 12
300 if (ull_id >= 0x20b000000000000 && ull_id <= 0x20b180000000000) return true;
301 if (ull_id >= 0x20b800000000000 && ull_id <= 0x20b980000000000) return true;
302
303 // Stave 13
304 if (ull_id >= 0x20c000000000000 && ull_id <= 0x20c180000000000) return true;
305 if (ull_id >= 0x20c800000000000 && ull_id <= 0x20c980000000000) return true;
306
307 // Stave 14
308 if (ull_id >= 0x20d000000000000 && ull_id <= 0x20d180000000000) return true;
309 if (ull_id >= 0x20d800000000000 && ull_id <= 0x20d980000000000) return true;
310
311 return false;
312}
313
317
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
std::pair< std::vector< unsigned int >, bool > res
static Double_t P(Double_t *tt, Double_t *par)
Hold pixel distortion data produced by PixelDistortionAlg.
Amg::Vector2D correction(uint32_t hashID, const Amg::Vector2D &locpos, const Amg::Vector3D &direction) const
std::unordered_map< uint32_t, unsigned long long > m_ids
Amg::Vector2D correctSimulation(uint32_t hashID, const Amg::Vector2D &locpos, const Amg::Vector3D &direction) const
static double getSurveyZ(const double localeta, const double localphi, const float *disto)
static double getInSituZ(const double localeta, const double eta_size, const double localphi, const double phi_size, const float *disto)
static bool isOldParam(const unsigned long long ull_id)
std::vector< float > getDistortionMap(uint32_t id) const
static bool isIBL3D(const unsigned long long ull_id)
Amg::Vector2D correctReconstruction(uint32_t hashID, const Amg::Vector2D &locpos, const Amg::Vector3D &direction) const
std::unordered_map< uint32_t, std::vector< float > > m_distortionMap
unsigned long long getId(uint32_t hashID) const
STL class.
int r
Definition globals.cxx:22
void search(TDirectory *td, const std::string &s, std::string cwd, node *n)
recursive directory search for TH1 and TH2 and TProfiles
Definition hcg.cxx:739
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Macro wrapping the nonstandard restrict keyword.