Project
Loading...
Searching...
No Matches
TrackParametrization.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
20#include <MathUtils/Cartesian.h>
21#include <GPUCommonLogger.h>
22
23#ifndef GPUCA_GPUCODE_DEVICE
24#include <iostream>
25#endif
26
27#ifndef GPUCA_ALIGPUCODE
28#include <fmt/printf.h>
30#endif
31
32using namespace o2::gpu;
33using namespace o2::track;
34
35//______________________________________________________________
36template <typename value_T>
37GPUd() TrackParametrization<value_T>::TrackParametrization(const dim3_t& xyz, const dim3_t& pxpypz, int charge, bool sectorAlpha, const PID pid)
38 : mX{0.f}, mAlpha{0.f}, mP{0.f}
39{
40 // construct track param from kinematics
41
42 // Alpha of the frame is defined as:
43 // sectorAlpha == false : -> angle of pt direction
44 // sectorAlpha == true : -> angle of the sector from X,Y coordinate for r>1
45 // angle of pt direction for r==0
46 //
47 //
48 constexpr value_t kSafe = 1e-5;
49 value_t radPos2 = xyz[0] * xyz[0] + xyz[1] * xyz[1];
50 value_t alp = 0;
51 if (sectorAlpha || radPos2 < 1) {
52 alp = gpu::CAMath::ATan2(pxpypz[1], pxpypz[0]);
53 } else {
54 alp = gpu::CAMath::ATan2(xyz[1], xyz[0]);
55 }
56 if (sectorAlpha) {
57 alp = math_utils::detail::angle2Alpha<value_t>(alp);
58 }
59 //
60 value_t sn, cs;
61 math_utils::detail::sincos(alp, sn, cs);
62 // protection against cosp<0
63 if (cs * pxpypz[0] + sn * pxpypz[1] < 0) {
64 LOG(debug) << "alpha from phiPos() will invalidate this track parameters, overriding to alpha from phi()";
65 alp = gpu::CAMath::ATan2(pxpypz[1], pxpypz[0]);
66 if (sectorAlpha) {
67 alp = math_utils::detail::angle2Alpha<value_t>(alp);
68 }
69 math_utils::detail::sincos(alp, sn, cs);
70 }
71
72 // protection: avoid alpha being too close to 0 or +-pi/2
73 if (gpu::CAMath::Abs(sn) < 2 * kSafe) {
74 if (alp > 0) {
75 alp += alp < constants::math::PIHalf ? 2 * kSafe : -2 * kSafe;
76 } else {
77 alp += alp > -constants::math::PIHalf ? -2 * kSafe : 2 * kSafe;
78 }
79 math_utils::detail::sincos(alp, sn, cs);
80 } else if (gpu::CAMath::Abs(cs) < 2 * kSafe) {
81 if (alp > 0) {
82 alp += alp > constants::math::PIHalf ? 2 * kSafe : -2 * kSafe;
83 } else {
84 alp += alp > -constants::math::PIHalf ? 2 * kSafe : -2 * kSafe;
85 }
86 math_utils::detail::sincos(alp, sn, cs);
87 }
88 // get the vertex of origin and the momentum
89 dim3_t ver{xyz[0], xyz[1], xyz[2]};
90 dim3_t mom{pxpypz[0], pxpypz[1], pxpypz[2]};
91 //
92 // Rotate to the local coordinate system
93 math_utils::detail::rotateZ<value_t>(ver, -alp);
94 math_utils::detail::rotateZ<value_t>(mom, -alp);
95 //
96 value_t ptI = 1.f / gpu::CAMath::Sqrt(mom[0] * mom[0] + mom[1] * mom[1]);
97 mX = ver[0];
98 mAlpha = alp;
99 mP[kY] = ver[1];
100 mP[kZ] = ver[2];
101 mP[kSnp] = mom[1] * ptI;
102 mP[kTgl] = mom[2] * ptI;
103 mAbsCharge = gpu::CAMath::Abs(charge);
104 mP[kQ2Pt] = charge ? ptI * charge : ptI;
105 mPID = pid;
106 //
107 if (gpu::CAMath::Abs(1 - getSnp()) < kSafe) {
108 mP[kSnp] = 1.f - kSafe; // Protection
109 } else if (gpu::CAMath::Abs(-1 - getSnp()) < kSafe) {
110 mP[kSnp] = -1.f + kSafe; // Protection
111 }
112 //
113}
114
115//_______________________________________________________
116template <typename value_T>
117GPUd() bool TrackParametrization<value_T>::getPxPyPzGlo(dim3_t& pxyz) const
118{
119 // track momentum
120 if (gpu::CAMath::Abs(getQ2Pt()) < constants::math::Almost0 || gpu::CAMath::Abs(getSnp()) > constants::math::Almost1) {
121 return false;
122 }
123 value_t cs, sn, pt = getPt();
124 value_t r = gpu::CAMath::Sqrt((1.f - getSnp()) * (1.f + getSnp()));
125 math_utils::detail::sincos(getAlpha(), sn, cs);
126 pxyz[0] = pt * (r * cs - getSnp() * sn);
127 pxyz[1] = pt * (getSnp() * cs + r * sn);
128 pxyz[2] = pt * getTgl();
129 return true;
130}
131
132//____________________________________________________
133template <typename value_T>
134GPUd() bool TrackParametrization<value_T>::getPosDirGlo(std::array<value_t, 9>& posdirp) const
135{
136 // fill vector with lab x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha
137 value_t ptI = getPtInv();
138 value_t snp = getSnp();
139 if (gpu::CAMath::Abs(snp) > constants::math::Almost1) {
140 return false;
141 }
142 value_t &sn = posdirp[7], &cs = posdirp[8];
143 value_t csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp));
144 value_t cstht = gpu::CAMath::Sqrt(1.f + getTgl() * getTgl());
145 value_t csthti = 1.f / cstht;
146 math_utils::detail::sincos(getAlpha(), sn, cs);
147 posdirp[0] = getX() * cs - getY() * sn;
148 posdirp[1] = getX() * sn + getY() * cs;
149 posdirp[2] = getZ();
150 posdirp[3] = (csp * cs - snp * sn) * csthti; // px/p
151 posdirp[4] = (snp * cs + csp * sn) * csthti; // py/p
152 posdirp[5] = getTgl() * csthti; // pz/p
153 posdirp[6] = cstht / ptI; // p
154 return true;
155}
156
157//______________________________________________________________
158template <typename value_T>
159GPUd() bool TrackParametrization<value_T>::rotateParam(value_t alpha)
160{
161 // rotate to alpha frame
162 if (gpu::CAMath::Abs(getSnp()) > constants::math::Almost1) {
163 LOGP(debug, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp());
164 return false;
165 }
166 //
167 math_utils::detail::bringToPMPi<value_t>(alpha);
168 //
169 value_t ca = 0, sa = 0;
170 math_utils::detail::sincos(alpha - getAlpha(), sa, ca);
171 value_t snp = getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp)); // Improve precision
172 // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle
173 // direction in local frame is along the X axis
174 if ((csp * ca + snp * sa) < 0) {
175 // LOGF(warning,"Rotation failed: local cos(phi) would become {:.2f}", csp * ca + snp * sa);
176 return false;
177 }
178 //
179 value_t tmp = snp * ca - csp * sa;
180 if (gpu::CAMath::Abs(tmp) > constants::math::Almost1) {
181 LOGP(debug, "Rotation failed: new snp {:.2f}", tmp);
182 return false;
183 }
184 value_t xold = getX(), yold = getY();
185 mAlpha = alpha;
186 mX = xold * ca + yold * sa;
187 mP[kY] = -xold * sa + yold * ca;
188 mP[kSnp] = tmp;
189 return true;
190}
191
192//______________________________________________________________
193template <typename value_T>
194GPUd() bool TrackParametrization<value_T>::rotateParam(value_t& alpha, value_t& ca, value_t& sa)
195{
196 // rotate to alpha frame
197 if (gpu::CAMath::Abs(getSnp()) > constants::math::Almost1) {
198 LOGP(debug, "Precondition is not satisfied: |sin(phi)|>1 ! {:f}", getSnp());
199 return false;
200 }
201 //
202 math_utils::detail::bringToPMPi<value_t>(alpha);
203 math_utils::detail::sincos(alpha - getAlpha(), sa, ca);
204 value_t snp = getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp)); // Improve precision
205 // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle direction in local frame is along the X axis
206 if ((csp * ca + snp * sa) < 0) {
207 // LOGF(warning,"Rotation failed: local cos(phi) would become {:.2f}", csp * ca + snp * sa);
208 return false;
209 }
210 //
211 value_t tmp = snp * ca - csp * sa;
212 if (gpu::CAMath::Abs(tmp) > constants::math::Almost1) {
213 LOGP(debug, "Rotation failed: new snp {:.2f}", tmp);
214 return false;
215 }
216 value_t xold = getX(), yold = getY();
217 mAlpha = alpha;
218 mX = xold * ca + yold * sa;
219 mP[kY] = -xold * sa + yold * ca;
220 mP[kSnp] = tmp;
221 return true;
222}
223
224//____________________________________________________________
225template <typename value_T>
226GPUd() bool TrackParametrization<value_T>::propagateParamTo(value_t xk, const dim3_t& b)
227{
228 //----------------------------------------------------------------
229 // Extrapolate this track params (w/o cov matrix) to the plane X=xk in the field b[].
230 //
231 // X [cm] is in the "tracking coordinate system" of this track.
232 // b[]={Bx,By,Bz} [kG] is in the Global coordidate system.
233 //----------------------------------------------------------------
234 value_t dx = xk - getX();
235 if (gpu::CAMath::Abs(dx) < constants::math::Almost0) {
236 return true;
237 }
238 // Do not propagate tracks outside the ALICE detector
239 if (gpu::CAMath::Abs(dx) > 1e5 || gpu::CAMath::Abs(getY()) > 1e5 || gpu::CAMath::Abs(getZ()) > 1e5) {
240 LOG(warning) << "Anomalous track, traget X:" << xk;
241 return false;
242 }
243 value_t crv = getCurvature(b[2]);
244 if (crv == 0.) {
245 return propagateParamTo(xk, 0.); // for the straight-line propagation use 1D field method
246 }
247
248 value_t x2r = crv * dx;
249 value_t f1 = getSnp(), f2 = f1 + x2r;
250 if (gpu::CAMath::Abs(f1) > constants::math::Almost1 || gpu::CAMath::Abs(f2) > constants::math::Almost1) {
251 return false;
252 }
253 value_t r1 = gpu::CAMath::Sqrt((1.f - f1) * (1.f + f1));
254 if (gpu::CAMath::Abs(r1) < constants::math::Almost0) {
255 return false;
256 }
257 value_t r2 = gpu::CAMath::Sqrt((1.f - f2) * (1.f + f2));
258 if (gpu::CAMath::Abs(r2) < constants::math::Almost0) {
259 return false;
260 }
261 value_t dy2dx = (f1 + f2) / (r1 + r2);
262 value_t step = (gpu::CAMath::Abs(x2r) < 0.05f) ? dx * gpu::CAMath::Abs(r2 + f2 * dy2dx) // chord
263 : 2.f * CAMath::ASin(0.5f * dx * gpu::CAMath::Sqrt(1.f + dy2dx * dy2dx) * crv) / crv; // arc
264 step *= gpu::CAMath::Sqrt(1.f + getTgl() * getTgl());
265 //
266 // get the track x,y,z,px/p,py/p,pz/p,p,sinAlpha,cosAlpha in the Global System
267 std::array<value_t, 9> vecLab{0.f};
268 if (!getPosDirGlo(vecLab)) {
269 return false;
270 }
271
272 // rotate to the system where Bx=By=0.
273 value_t bxy2 = b[0] * b[0] + b[1] * b[1];
274 value_t bt = gpu::CAMath::Sqrt(bxy2);
275 value_t cosphi = 1.f, sinphi = 0.f;
276 if (bt > constants::math::Almost0) {
277 cosphi = b[0] / bt;
278 sinphi = b[1] / bt;
279 }
280 value_t bb = gpu::CAMath::Sqrt(bxy2 + b[2] * b[2]);
281 value_t costet = 1.f, sintet = 0.f;
282 if (bb > constants::math::Almost0) {
283 costet = b[2] / bb;
284 sintet = bt / bb;
285 }
286 std::array<value_t, 7> vect{costet * cosphi * vecLab[0] + costet * sinphi * vecLab[1] - sintet * vecLab[2],
287 -sinphi * vecLab[0] + cosphi * vecLab[1],
288 sintet * cosphi * vecLab[0] + sintet * sinphi * vecLab[1] + costet * vecLab[2],
289 costet * cosphi * vecLab[3] + costet * sinphi * vecLab[4] - sintet * vecLab[5],
290 -sinphi * vecLab[3] + cosphi * vecLab[4],
291 sintet * cosphi * vecLab[3] + sintet * sinphi * vecLab[4] + costet * vecLab[5],
292 vecLab[6]};
293
294 // Do the helix step
295 value_t q = getCharge();
296 g3helx3(q * bb, step, vect);
297
298 // rotate back to the Global System
299 vecLab[0] = cosphi * costet * vect[0] - sinphi * vect[1] + cosphi * sintet * vect[2];
300 vecLab[1] = sinphi * costet * vect[0] + cosphi * vect[1] + sinphi * sintet * vect[2];
301 vecLab[2] = -sintet * vect[0] + costet * vect[2];
302
303 vecLab[3] = cosphi * costet * vect[3] - sinphi * vect[4] + cosphi * sintet * vect[5];
304 vecLab[4] = sinphi * costet * vect[3] + cosphi * vect[4] + sinphi * sintet * vect[5];
305 vecLab[5] = -sintet * vect[3] + costet * vect[5];
306
307 // rotate back to the Tracking System
308 value_t sinalp = -vecLab[7], cosalp = vecLab[8];
309 value_t t = cosalp * vecLab[0] - sinalp * vecLab[1];
310 vecLab[1] = sinalp * vecLab[0] + cosalp * vecLab[1];
311 vecLab[0] = t;
312 t = cosalp * vecLab[3] - sinalp * vecLab[4];
313 vecLab[4] = sinalp * vecLab[3] + cosalp * vecLab[4];
314 vecLab[3] = t;
315
316 // Do the final correcting step to the target plane (linear approximation)
317 value_t x = vecLab[0], y = vecLab[1], z = vecLab[2];
318 if (gpu::CAMath::Abs(x - xk) > constants::math::Almost0) {
319 if (gpu::CAMath::Abs(vecLab[3]) < constants::math::Almost0) {
320 return false;
321 }
322 auto dxFin = xk - vecLab[0];
323 x += dxFin;
324 y += vecLab[4] / vecLab[3] * dxFin;
325 z += vecLab[5] / vecLab[3] * dxFin;
326 }
327
328 // Calculate the track parameters
329 t = 1.f / gpu::CAMath::Sqrt(vecLab[3] * vecLab[3] + vecLab[4] * vecLab[4]);
330 mX = xk;
331 mP[kY] = y;
332 mP[kZ] = z;
333 mP[kSnp] = vecLab[4] * t;
334 mP[kTgl] = vecLab[5] * t;
335 mP[kQ2Pt] = q * t / vecLab[6];
336
337 return true;
338}
339
340//____________________________________________________________
341template <typename value_T>
342GPUd() bool TrackParametrization<value_T>::propagateParamTo(value_t xk, value_t b)
343{
344 //----------------------------------------------------------------
345 // propagate this track to the plane X=xk (cm) in the field "b" (kG)
346 // Only parameters are propagated, not the matrix. To be used for small
347 // distances only (<mm, i.e. misalignment)
348 //----------------------------------------------------------------
349 value_t dx = xk - getX();
350 if (gpu::CAMath::Abs(dx) < constants::math::Almost0) {
351 return true;
352 }
353 value_t crv = (gpu::CAMath::Abs(b) < constants::math::Almost0) ? 0.f : getCurvature(b);
354 value_t x2r = crv * dx;
355 value_t f1 = getSnp(), f2 = f1 + x2r;
356 if ((gpu::CAMath::Abs(f1) > constants::math::Almost1) || (gpu::CAMath::Abs(f2) > constants::math::Almost1)) {
357 return false;
358 }
359 value_t r1 = gpu::CAMath::Sqrt((1.f - f1) * (1.f + f1));
360 if (gpu::CAMath::Abs(r1) < constants::math::Almost0) {
361 return false;
362 }
363 value_t r2 = gpu::CAMath::Sqrt((1.f - f2) * (1.f + f2));
364 if (gpu::CAMath::Abs(r2) < constants::math::Almost0) {
365 return false;
366 }
367 double dy2dx = (f1 + f2) / (r1 + r2);
368 bool arcz = gpu::CAMath::Abs(x2r) > 0.05f;
369 if (arcz) {
370 // for small dx/R the linear apporximation of the arc by the segment is OK,
371 // but at large dx/R the error is very large and leads to incorrect Z propagation
372 // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi
373 // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2)
374 // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one
375 // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center
376 // track1 += rot/crv*track3;
377 //
378 auto arg = r1 * f2 - r2 * f1;
379 if (gpu::CAMath::Abs(arg) > constants::math::Almost1) {
380 return false;
381 }
382 value_t rot = CAMath::ASin(arg); // more economic version from Yura.
383 if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles
384 if (f2 > 0.f) {
385 rot = constants::math::PI - rot; //
386 } else {
387 rot = -constants::math::PI - rot;
388 }
389 }
390 mP[kZ] += getTgl() / crv * rot;
391 } else {
392 mP[kZ] += dx * (r2 + f2 * dy2dx) * getTgl();
393 }
394 mX = xk;
395 mP[kY] += dx * dy2dx;
396 mP[kSnp] += x2r;
397 return true;
398}
399
400//_______________________________________________________________________
401template <typename value_T>
402GPUd() bool TrackParametrization<value_T>::propagateParamToDCA(const math_utils::Point3D<value_t>& vtx, value_t b, dim2_t* dca, value_t maxD)
403{
404 // propagate track to DCA to the vertex
405 value_t sn, cs, alp = getAlpha();
406 math_utils::detail::sincos(alp, sn, cs);
407 value_t x = getX(), y = getY(), snp = getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp));
408 value_t xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
409 x -= xv;
410 y -= yv;
411 // Estimate the impact parameter neglecting the track curvature
412 value_t d = gpu::CAMath::Abs(x * snp - y * csp);
413 if (d > maxD) {
414 if (dca) { // provide default DCA for failed propag
415 (*dca)[0] = o2::track::DefaultDCA;
416 (*dca)[1] = o2::track::DefaultDCA;
417 }
418 return false;
419 }
420 value_t crv = getCurvature(b);
421 value_t tgfv = -(crv * x - snp) / (crv * y + csp);
422 sn = tgfv / gpu::CAMath::Sqrt(1.f + tgfv * tgfv);
423 cs = gpu::CAMath::Sqrt((1.f - sn) * (1.f + sn));
424 cs = (gpu::CAMath::Abs(tgfv) > constants::math::Almost0) ? sn / tgfv : constants::math::Almost1;
425
426 x = xv * cs + yv * sn;
427 yv = -xv * sn + yv * cs;
428 xv = x;
429
430 auto tmpT(*this); // operate on the copy to recover after the failure
431 alp += gpu::CAMath::ASin(sn);
432 if (!tmpT.rotateParam(alp) || !tmpT.propagateParamTo(xv, b)) {
433#ifndef GPUCA_ALIGPUCODE
434 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex "
435 << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: " << tmpT.asString();
436#else
437 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z();
438#endif
439 if (dca) { // provide default DCA for failed propag
440 (*dca)[0] = o2::track::DefaultDCA;
441 (*dca)[1] = o2::track::DefaultDCA;
442 }
443 return false;
444 }
445 *this = tmpT;
446 if (dca) {
447 (*dca)[0] = getY() - yv;
448 (*dca)[1] = getZ() - zv;
449 }
450 return true;
451}
452
453//____________________________________________________________
454template <typename value_T>
455GPUd() bool TrackParametrization<value_T>::getYZAt(value_t xk, value_t b, value_t& y, value_t& z) const
456{
457 //----------------------------------------------------------------
458 // estimate Y,Z in tracking frame at given X
459 //----------------------------------------------------------------
460 value_t dx = xk - getX();
461 y = mP[kY];
462 z = mP[kZ];
463 if (gpu::CAMath::Abs(dx) < constants::math::Almost0) {
464 return true;
465 }
466 value_t crv = getCurvature(b);
467 value_t x2r = crv * dx;
468 value_t f1 = getSnp(), f2 = f1 + x2r;
469 if ((gpu::CAMath::Abs(f1) > constants::math::Almost1) || (gpu::CAMath::Abs(f2) > constants::math::Almost1)) {
470 return false;
471 }
472 value_t r1 = gpu::CAMath::Sqrt((1.f - f1) * (1.f + f1));
473 if (gpu::CAMath::Abs(r1) < constants::math::Almost0) {
474 return false;
475 }
476 value_t r2 = gpu::CAMath::Sqrt((1.f - f2) * (1.f + f2));
477 if (gpu::CAMath::Abs(r2) < constants::math::Almost0) {
478 return false;
479 }
480 double dy2dx = (f1 + f2) / (r1 + r2);
481 y += dx * dy2dx;
482 if (gpu::CAMath::Abs(x2r) < 0.05f) {
483 z += dx * (r2 + f2 * dy2dx) * getTgl();
484 } else {
485 // for small dx/R the linear apporximation of the arc by the segment is OK,
486 // but at large dx/R the error is very large and leads to incorrect Z propagation
487 // angle traversed delta = 2*asin(dist_start_end / R / 2), hence the arc is: R*deltaPhi
488 // The dist_start_end is obtained from sqrt(dx^2+dy^2) = x/(r1+r2)*sqrt(2+f1*f2+r1*r2)
489 // double chord = dx*TMath::Sqrt(1+dy2dx*dy2dx); // distance from old position to new one
490 // double rot = 2*TMath::ASin(0.5*chord*crv); // angular difference seen from the circle center
491 // track1 += rot/crv*track3;
492 //
493 value_t rot = CAMath::ASin(r1 * f2 - r2 * f1); // more economic version from Yura.
494 if (f1 * f1 + f2 * f2 > 1.f && f1 * f2 < 0.f) { // special cases of large rotations or large abs angles
495 if (f2 > 0.f) {
496 rot = constants::math::PI - rot; //
497 } else {
498 rot = -constants::math::PI - rot;
499 }
500 }
501 z += getTgl() / crv * rot;
502 }
503 return true;
504}
505
506//______________________________________________________________
507template <typename value_T>
508GPUd() void TrackParametrization<value_T>::invertParam()
509{
510 // Transform this track to the local coord. system rotated by 180 deg.
511 mX = -mX;
512 mAlpha += constants::math::PI;
513 math_utils::detail::bringToPMPi<value_t>(mAlpha);
514 //
515 mP[0] = -mP[0];
516 mP[3] = -mP[3];
517 mP[4] = -mP[4];
518 //
519}
520
521//______________________________________________________________
522template <typename value_T>
523GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getZAt(value_t xk, value_t b) const
524{
526 value_t y, z;
527 return getYZAt(xk, b, y, z) ? z : -9999.f;
528}
529
530//______________________________________________________________
531template <typename value_T>
532GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getYAt(value_t xk, value_t b) const
533{
535 value_t y, z;
536 return getYZAt(xk, b, y, z) ? y : -9999.f;
537}
538
539//______________________________________________________________
540template <typename value_T>
541GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getSnpAt(value_t xk, value_t b) const
542{
544 value_t dx = xk - getX();
545 if (gpu::CAMath::Abs(dx) < constants::math::Almost0) {
546 return getSnp();
547 }
548 value_t crv = (gpu::CAMath::Abs(b) < constants::math::Almost0) ? 0.f : getCurvature(b);
549 value_t x2r = crv * dx;
550 return mP[kSnp] + x2r;
551}
552
553//______________________________________________________________
554template <typename value_T>
555GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhiAt(value_t xk, value_t b) const
556{
558 value_t dx = xk - getX();
559 if (gpu::CAMath::Abs(dx) < constants::math::Almost0) {
560 return getPhi();
561 }
562 value_t crv = (gpu::CAMath::Abs(b) < constants::math::Almost0) ? 0.f : getCurvature(b);
563 value_t x2r = crv * dx;
564 value_t snp = mP[kSnp] + x2r;
565 value_t phi = 999.;
566 if (gpu::CAMath::Abs(snp) < constants::math::Almost1) {
567 phi = gpu::CAMath::ASin(snp) + getAlpha();
568 math_utils::detail::bringTo02Pi<value_t>(phi);
569 }
570 return phi;
571}
572
573//______________________________________________________________
574template <typename value_T>
575GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getPhiPosAt(value_t xk, value_t b) const
576{
578 value_t phi = 999.;
579 auto y = getYAt(xk, b);
580 if (y > -9998.) {
581 phi = gpu::CAMath::ATan2(y, xk) + getAlpha();
582 math_utils::detail::bringTo02Pi<value_t>(phi);
583 }
584 return phi;
585}
586
587//______________________________________________________________
588template <typename value_T>
589GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getSnpAt(value_t alpha, value_t xk, value_t b) const
590{
592 math_utils::detail::bringToPMPi<value_t>(alpha);
593 value_t ca = 0, sa = 0;
594 math_utils::detail::sincos(alpha - getAlpha(), sa, ca);
595 value_t snp = getSnp(), csp = gpu::CAMath::Sqrt((1.f - snp) * (1.f + snp)); // Improve precision
596 // RS: check if rotation does no invalidate track model (cos(local_phi)>=0, i.e. particle direction in local frame is along the X axis
597 if ((csp * ca + snp * sa) < 0.) {
598 // LOGF(warning,"Rotation failed: local cos(phi) would become {:.2f}", csp * ca + snp * sa);
599 return -999;
600 }
601 value_t tmp = snp * ca - csp * sa;
602 if (gpu::CAMath::Abs(tmp) > constants::math::Almost1) {
603 LOGP(debug, "Rotation failed: new snp {:.2f}", tmp);
604 return -999;
605 }
606 value_t xrot = getX() * ca + getY() * sa;
607 value_t dx = xk - xrot;
608 value_t crv = (gpu::CAMath::Abs(b) < constants::math::Almost0) ? 0.f : getCurvature(b);
609 value_t x2r = crv * dx;
610 return tmp + x2r;
611}
612
613#ifndef GPUCA_ALIGPUCODE
614//_____________________________________________________________
615template <typename value_T>
617{
618 // print parameters as string
619 return fmt::format("X:{:+.4e} Alp:{:+.3e} Par: {:+.4e} {:+.4e} {:+.4e} {:+.4e} {:+.4e} |Q|:{:d} {:s}",
620 getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge(), getPID().getName());
621}
622
623//_____________________________________________________________
624template <typename value_T>
626{
627 auto _X = getX();
628 auto _Alpha = getAlpha();
629 auto _Y = getY();
630 auto _Z = getZ();
631 auto _Snp = getSnp();
632 auto _Tgl = getTgl();
633 float _Q2Pt = getQ2Pt();
634 float _AbsCharge = getAbsCharge();
635 // print parameters as string
636 return fmt::format("X:{:x} Alp:{:x} Par: {:x} {:x} {:x} {:x} {:x} |Q|:{:x} {:s}\n",
637 reinterpret_cast<const unsigned int&>(_X),
638 reinterpret_cast<const unsigned int&>(_Alpha),
639 reinterpret_cast<const unsigned int&>(_Y),
640 reinterpret_cast<const unsigned int&>(_Z),
641 reinterpret_cast<const unsigned int&>(_Snp),
642 reinterpret_cast<const unsigned int&>(_Tgl),
643 reinterpret_cast<const unsigned int&>(_Q2Pt),
644 reinterpret_cast<const unsigned int&>(_AbsCharge),
645 getPID().getName());
646}
647#endif
648
649//______________________________________________________________
650template <typename value_T>
651GPUd() void TrackParametrization<value_T>::printParam() const
652{
653 // print parameters
654#ifndef GPUCA_ALIGPUCODE
655 printf("%s\n", asString().c_str());
656#elif !defined(GPUCA_GPUCODE_DEVICE) || (!defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT))
657 printf("X:%+.4e Alp:%+.3e Par: %+.4e %+.4e %+.4e %+.4e %+.4e |Q|:%d %s\n",
658 getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge(), getPID().getName());
659#endif
660}
661
662//______________________________________________________________
663template <typename value_T>
664GPUd() void TrackParametrization<value_T>::printParamHexadecimal()
665{
666 // print parameters
667#ifndef GPUCA_ALIGPUCODE
668 printf("%s\n", asStringHexadecimal().c_str());
669#elif !defined(GPUCA_GPUCODE_DEVICE) || (!defined(__OPENCL__) && defined(GPUCA_GPU_DEBUG_PRINT))
670 printf("X:%x Alp:%x Par: %x %x %x %x %x |Q|:%x %s\n",
671 gpu::CAMath::Float2UIntReint(getX()),
672 gpu::CAMath::Float2UIntReint(getAlpha()),
673 gpu::CAMath::Float2UIntReint(getY()),
674 gpu::CAMath::Float2UIntReint(getZ()),
675 gpu::CAMath::Float2UIntReint(getSnp()),
676 gpu::CAMath::Float2UIntReint(getTgl()),
677 gpu::CAMath::Float2UIntReint(getQ2Pt()),
678 gpu::CAMath::Float2UIntReint(getAbsCharge()),
679 getPID().getName());
680#endif
681}
682
683//______________________________________________________________
684template <typename value_T>
685GPUd() bool TrackParametrization<value_T>::getXatLabR(value_t r, value_t& x, value_t bz, track::DirType dir) const
686{
687 // Get local X of the track position estimated at the radius lab radius r.
688 // The track curvature is accounted exactly
689 //
690 // The flag "dir" can be used to remove the ambiguity of which intersection to take (out of 2 possible)
691 // DirAuto (==0) - take the intersection closest to the current track position
692 // DirOutward (==1) - go along the track (increasing mX)
693 // DirInward (==-1) - go backward (decreasing mX)
694 //
695 const double fy = mP[0], sn = mP[2];
696 const value_t kEps = 1.e-6;
697 //
698 if (gpu::CAMath::Abs(getSnp()) > constants::math::Almost1) {
699 return false;
700 }
701 auto crv = getCurvature(bz);
702 while (gpu::CAMath::Abs(crv) > constants::math::Almost0) { // helix ?
703 // get center of the track circle
705 getCircleParamsLoc(bz, circle);
706 if (circle.rC == 0.) {
707 crv = 0.;
708 break;
709 }
710 value_t r0 = gpu::CAMath::Sqrt(circle.getCenterD2());
711 if (r0 <= constants::math::Almost0) {
712 return false; // the track is concentric to circle
713 }
714 double tR2r0 = 1., g = 0., tmp = 0.;
715 if (gpu::CAMath::Abs(circle.rC - r0) > kEps) {
716 tR2r0 = circle.rC / r0;
717 g = 0.5f * (r * r / (r0 * circle.rC) - tR2r0 - 1.f / tR2r0);
718 tmp = 1.f + g * tR2r0;
719 } else {
720 tR2r0 = 1.0;
721 g = 0.5 * r * r / (r0 * circle.rC) - 1.;
722 tmp = 0.5 * r * r / (r0 * r0);
723 }
724 auto det = (1. - g) * (1. + g);
725 if (det < 0.) {
726 return false; // does not reach raduis r
727 }
728 det = gpu::CAMath::Sqrt(det);
729 //
730 // the intersection happens in 2 points: {circle.xC+tR*C,circle.yC+tR*S}
731 // with C=f*c0+-|s0|*det and S=f*s0-+c0 sign(s0)*det
732 // where s0 and c0 make direction for the circle center (=circle.xC/r0 and circle.yC/r0)
733 //
734 x = circle.xC * tmp;
735 auto y = circle.yC * tmp;
736 if (gpu::CAMath::Abs(circle.yC) > constants::math::Almost0) { // when circle.yC==0 the x,y is unique
737 auto dfx = tR2r0 * gpu::CAMath::Abs(circle.yC) * det;
738 auto dfy = tR2r0 * circle.xC * (circle.yC > 0. ? det : -det);
739 if (dir == DirAuto) { // chose the one which corresponds to smallest step
740 auto delta = (x - mX) * dfx - (y - fy) * dfy; // the choice of + in C will lead to smaller step if delta<0
741 x += delta < 0. ? dfx : -dfx;
742 } else if (dir == DirOutward) { // along track direction: x must be > mX
743 x -= dfx; // try the smallest step (dfx is positive)
744 auto dfeps = mX - x; // handle special case of very small step
745 if (dfeps < -kEps) {
746 return true;
747 }
748 if (gpu::CAMath::Abs(dfeps) < kEps && gpu::CAMath::Abs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r?
749 x = mX;
750 return true;
751 }
752 x += dfx + dfx;
753 auto dxm = x - mX;
754 if (dxm > 0.) {
755 return true;
756 } else if (dxm < -kEps) {
757 return false;
758 }
759 x = mX; // don't move
760 } else { // backward: x must be < mX
761 x += dfx; // try the smallest step (dfx is positive)
762 auto dfeps = x - mX; // handle special case of very small step
763 if (dfeps < -kEps) {
764 return true;
765 }
766 if (gpu::CAMath::Abs(dfeps) < kEps && gpu::CAMath::Abs(mX * mX + fy * fy - r * r) < kEps) { // are we already in right r?
767 x = mX;
768 return true;
769 }
770 x -= dfx + dfx;
771 auto dxm = x - mX;
772 if (dxm < 0.) {
773 return true;
774 }
775 if (dxm > kEps) {
776 return false;
777 }
778 x = mX; // don't move
779 }
780 } else { // special case: track touching the circle just in 1 point
781 if ((dir == DirOutward && x < mX) || (dir == DirInward && x > mX)) {
782 return false;
783 }
784 }
785 return true;
786 }
787 // this is a straight track
788 if (gpu::CAMath::Abs(sn) >= constants::math::Almost1) { // || to Y axis
789 double det = (r - mX) * (r + mX);
790 if (det < 0.f) {
791 return false; // does not reach raduis r
792 }
793 x = mX;
794 if (dir == DirAuto) {
795 return true;
796 }
797 det = gpu::CAMath::Sqrt(det);
798 if (dir == DirOutward) { // along the track direction
799 if (sn > 0.) {
800 if (fy > det) {
801 return false; // track is along Y axis and above the circle
802 }
803 } else {
804 if (fy < -det) {
805 return false; // track is against Y axis amd belo the circle
806 }
807 }
808 } else if (dir == DirInward) { // against track direction
809 if (sn > 0.) {
810 if (fy < -det) {
811 return false; // track is along Y axis
812 }
813 } else if (fy > det) {
814 return false; // track is against Y axis
815 }
816 }
817 } else if (gpu::CAMath::Abs(sn) <= constants::math::Almost0) { // || to X axis
818 double det = (r - fy) * (r + fy);
819 if (det < 0.) {
820 return false; // does not reach raduis r
821 }
822 det = gpu::CAMath::Sqrt(det);
823 if (dir == DirAuto) {
824 x = mX > 0. ? det : -det; // choose the solution requiring the smalest step
825 return true;
826 } else if (dir == DirOutward) { // along the track direction
827 if (mX > det) {
828 return false; // current point is in on the right from the circle
829 } else {
830 x = (mX < -det) ? -det : det; // on the left : within the circle
831 }
832 } else { // against the track direction
833 if (mX < -det) {
834 return false;
835 } else {
836 x = mX > det ? det : -det;
837 }
838 }
839 } else { // general case of straight line
840 auto cs = gpu::CAMath::Sqrt((1. - sn) * (1. + sn));
841 auto xsyc = mX * sn - fy * cs;
842 auto det = (r - xsyc) * (r + xsyc);
843 if (det < 0.) {
844 return false; // does not reach raduis r
845 }
846 det = gpu::CAMath::Sqrt(det);
847 auto xcys = mX * cs + fy * sn;
848 auto t = -xcys;
849 if (dir == DirAuto) {
850 t += t > 0. ? -det : det; // chose the solution requiring the smalest step
851 } else if (dir > 0) { // go in increasing mX direction. ( t+-det > 0)
852 if (t >= -det) {
853 t += det; // take minimal step giving t>0
854 } else {
855 return false; // both solutions have negative t
856 }
857 } else { // go in decreasing mX direction. (t+-det < 0)
858 if (t < det) {
859 t -= det; // take minimal step giving t<0
860 } else {
861 return false; // both solutions have positive t
862 }
863 }
864 x = mX + cs * t;
865 }
866 //
867 return true;
868}
869
870//______________________________________________
871template <typename value_T>
872GPUd() bool TrackParametrization<value_T>::correctForELoss(value_t xrho, bool anglecorr)
873{
874 //------------------------------------------------------------------
875 // This function corrects the track parameters for the energy loss in crossed material.
876 // "xrho" - is the product length*density (g/cm^2).
877 // It should be passed as negative when propagating tracks
878 // from the intreaction point to the outside of the central barrel.
879 // "dedx" - mean enery loss (GeV/(g/cm^2), if <=kCalcdEdxAuto : calculate on the fly
880 // "anglecorr" - switch for the angular correction
881 //------------------------------------------------------------------
882 constexpr value_t kMinP = 0.01f; // kill below this momentum
883
884 auto m = getPID().getMass();
885 if (m > 0 && xrho != 0.f) {
886 // Apply angle correction, if requested
887 if (anglecorr) {
888 value_t csp2 = (1.f - getSnp()) * (1.f + getSnp()); // cos(phi)^2
889 value_t cst2I = (1.f + getTgl() * getTgl()); // 1/cos(lambda)^2
890 value_t angle = gpu::CAMath::Sqrt(cst2I / (csp2));
891 xrho *= angle;
892 }
893 int charge2 = getAbsCharge() * getAbsCharge();
894 value_t p = getP(), p0 = p, p2 = p * p, e2 = p2 + getPID().getMass2(), massInv = 1. / m, bg = p * massInv;
895 value_t e = gpu::CAMath::Sqrt(e2), ekin = e - m, dedx = getdEdxBBOpt(bg);
896#ifdef _BB_NONCONST_CORR_
897 value_t dedxDer = 0., dedx1 = dedx;
898#endif
899 if (charge2 != 1) {
900 dedx *= charge2;
901 }
902 value_t dE = dedx * xrho;
903 int na = 1 + int(gpu::CAMath::Abs(dE) / ekin * ELoss2EKinThreshInv);
904 if (na > MaxELossIter) {
905 na = MaxELossIter;
906 }
907 if (na > 1) {
908 dE /= na;
909 xrho /= na;
910#ifdef _BB_NONCONST_CORR_
911 dedxDer = getBetheBlochSolidDerivativeApprox(dedx1, bg); // require correction for non-constantness of dedx vs betagamma
912 if (charge2 != 1) {
913 dedxDer *= charge2;
914 }
915#endif
916 }
917 while (na--) {
918#ifdef _BB_NONCONST_CORR_
919 if (dedxDer != 0.) { // correction for non-constantness of dedx vs beta*gamma (in linear approximation): for a single step dE -> dE * [(exp(dedxDer) - 1)/dedxDer]
920 if (xrho < 0) {
921 dedxDer = -dedxDer; // E.loss ( -> positive derivative)
922 }
923 auto corrC = (gpu::CAMath::Exp(dedxDer) - 1.) / dedxDer;
924 dE *= corrC;
925 }
926#endif
927 e += dE;
928 if (e > m) { // stopped
929 p = gpu::CAMath::Sqrt(e * e - getPID().getMass2());
930 } else {
931 return false;
932 }
933 if (na) {
934 bg = p * massInv;
935 dedx = getdEdxBBOpt(bg);
936#ifdef _BB_NONCONST_CORR_
937 dedxDer = getBetheBlochSolidDerivativeApprox(dedx, bg);
938#endif
939 if (charge2 != 1) {
940 dedx *= charge2;
941#ifdef _BB_NONCONST_CORR_
942 dedxDer *= charge2;
943#endif
944 }
945 dE = dedx * xrho;
946 }
947 }
948
949 if (p < kMinP) {
950 return false;
951 }
952 setQ2Pt(getQ2Pt() * p0 / p);
953 }
954
955 return true;
956}
957
958//______________________________________________
959template <typename value_T>
960GPUd() typename o2::track::TrackParametrization<value_T>::yzerr_t TrackParametrization<value_T>::getVertexInTrackFrame(const o2::dataformats::VertexBase& v) const
961{
962 // rotate vertex to track frame and return parameters used by getPredictedChi2 and update of TrackParametrizationWithError
963 value_t sn, cs;
964 math_utils::detail::sincos(-mAlpha, sn, cs); // use -alpha since we rotate from lab to tracking frame
965 value_t sn2 = sn * sn, cs2 = cs * cs, sncs = sn * cs;
966 value_t dsxysncs = 2. * v.getSigmaXY() * sncs;
967 return {{/*v.getX()*cs-v.getY()*sn,*/ v.getX() * sn + v.getY() * cs, v.getZ()},
968 {v.getSigmaX2() * sn2 + dsxysncs + v.getSigmaY2() * cs2, (sn + cs) * v.getSigmaYZ(), v.getSigmaZ2()}};
969}
970
971//______________________________________________
972template <typename value_T>
973GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getDCAYtoMV(value_t b, value_t xmv, value_t ymv, value_t zmv) const
974{
975 auto ttmp = *this;
976 dim2_t dca;
977 return ttmp.propagateParamToDCA({xmv, ymv, zmv}, b, &dca) ? dca[0] : -9999.;
978}
979
980//______________________________________________
981template <typename value_T>
982GPUd() typename TrackParametrization<value_T>::value_t TrackParametrization<value_T>::getDCAZtoMV(value_t b, value_t xmv, value_t ymv, value_t zmv) const
983{
984 auto ttmp = *this;
985 dim2_t dca;
986 return ttmp.propagateParamToDCA({xmv, ymv, zmv}, b, &dca) ? dca[1] : -9999.;
987}
988
989#ifndef GPUCA_ALIGPUCODE
990//______________________________________________
991template <typename value_T>
993{
994 auto p = getXYZGlo();
995 t.setZ(p.Z());
996 t.setX(p.X());
997 t.setY(p.Y());
998 t.setPhi(getPhi());
999 t.setTanl(getTgl());
1000 t.setInvQPt(getQ2Pt());
1001}
1002#endif
1003
1004namespace o2::track
1005{
1006#if !defined(GPUCA_GPUCODE) || defined(GPUCA_GPUCODE_DEVICE) // FIXME: DR: WORKAROUND to avoid CUDA bug creating host symbols for device code.
1007template class TrackParametrization<float>;
1008#endif
1009#ifndef GPUCA_GPUCODE
1010template class TrackParametrization<double>;
1011#endif
1012} // namespace o2::track
std::string getName(const TDataMember *dm, int index, int size)
std::string asString(TDataMember const &dm, char *pointer)
std::ostringstream debug
int16_t charge
Definition RawEventData.h:5
const int16_t bb
constexpr int p2()
uint16_t pid
Definition RawData.h:2
Base forward track model, params only, w/o covariance.
void setTanl(Double_t tanl)
Definition TrackFwd.h:80
void setInvQPt(Double_t invqpt)
Definition TrackFwd.h:85
void setPhi(Double_t phi)
Definition TrackFwd.h:64
void setX(Double_t x)
Definition TrackFwd.h:59
void setZ(Double_t z)
set Z coordinate (cm)
Definition TrackFwd.h:57
void setY(Double_t y)
Definition TrackFwd.h:62
void toFwdTrackPar(TrackParFwd &t) const
std::string asString() const
GLfloat GLfloat GLfloat alpha
Definition glcorearb.h:279
GLint GLenum GLint x
Definition glcorearb.h:403
const GLfloat * m
Definition glcorearb.h:4066
const GLdouble * v
Definition glcorearb.h:832
GLenum array
Definition glcorearb.h:4274
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean GLboolean g
Definition glcorearb.h:1233
GLfloat angle
Definition glcorearb.h:4071
GLboolean r
Definition glcorearb.h:1233
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
typename trackParam_t::dim3_t dim3_t
Definition utils.h:32
typename trackParam_t::dim2_t dim2_t
Definition utils.h:31
typename trackParam_t::value_t value_t
Definition utils.h:30
constexpr float Almost1
std::array< int, 24 > p0
double * getX(double *xyDxy, int N)
double * getY(double *xyDxy, int N)
value_T bg
Definition TrackUtils.h:194
value_T step
Definition TrackUtils.h:42
value_T f1
Definition TrackUtils.h:91
const value_T x
Definition TrackUtils.h:136
value_T std::array< value_T, 7 > & vect
Definition TrackUtils.h:42
GPUd() value_T BetheBlochSolid(value_T bg
Definition TrackUtils.h:150
value_T f2
Definition TrackUtils.h:92
constexpr float DefaultDCA
constexpr int MaxELossIter
constexpr float ELoss2EKinThreshInv
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Defining DataPointCompositeObject explicitly as copiable.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"