Project
Loading...
Searching...
No Matches
Propagator.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
13#include "GPUCommonLogger.h"
14#include "GPUCommonConstants.h"
15#include "GPUCommonMath.h"
17#include "MathUtils/Utils.h"
20
21using namespace o2::base;
22using namespace o2::gpu;
23
24#if !defined(GPUCA_GPUCODE)
25#include "Field/MagFieldFast.h" // Don't use this on the GPU
26#endif
27
28#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE)
29#include "Field/MagneticField.h"
33#include <FairRunAna.h> // eventually will get rid of it
34#include <TGeoGlobalMagField.h>
35
36template <typename value_T>
38{
39 if (uninitialized) {
40 return;
41 }
43 updateField();
44}
45
46//____________________________________________________________
47template <typename value_T>
49{
50 if (!mField) {
51 mField = static_cast<o2::field::MagneticField*>(TGeoGlobalMagField::Instance()->GetField());
52 if (!mField) {
53 LOG(warning) << "No Magnetic Field in TGeoGlobalMagField, checking legacy FairRunAna";
54 mField = dynamic_cast<o2::field::MagneticField*>(FairRunAna::Instance()->GetField());
55 }
56 if (!mField) {
57 LOG(fatal) << "Magnetic field is not initialized!";
58 }
59 if (!mField->getFastField() && mField->fastFieldExists()) {
60 mField->AllowFastField(true);
61 mFieldFast = mField->getFastField();
62 }
63 }
64 const value_type xyz[3] = {0.};
65 if (mFieldFast) {
66 mFieldFast->GetBz(xyz, mNominalBz);
67 } else {
68 mNominalBz = mField->GetBz(xyz[0], xyz[1], xyz[2]);
69 }
70}
71
72//____________________________________________________________
73template <typename value_T>
74int PropagatorImpl<value_T>::initFieldFromGRP(const std::string grpFileName, bool verbose)
75{
77 if (verbose) {
78 LOG(info) << "Loading field from GRP of " << grpFileName;
79 }
80 const auto grp = o2::parameters::GRPObject::loadFrom(grpFileName);
81 if (!grp) {
82 return -1;
83 }
84 if (verbose) {
85 grp->print();
86 }
87
88 return initFieldFromGRP(grp);
89}
90
91//____________________________________________________________
92template <typename value_T>
94{
96
97 if (TGeoGlobalMagField::Instance()->IsLocked()) {
98 if (TGeoGlobalMagField::Instance()->GetField()->TestBit(o2::field::MagneticField::kOverrideGRP)) {
99 LOG(warning) << "ExpertMode!!! GRP information will be ignored";
100 LOG(warning) << "ExpertMode!!! Running with the externally locked B field";
101 return 0;
102 } else {
103 LOG(info) << "Destroying existing B field instance";
104 delete TGeoGlobalMagField::Instance();
105 }
106 }
108 TGeoGlobalMagField::Instance()->SetField(fld);
109 TGeoGlobalMagField::Instance()->Lock();
110 if (verbose) {
111 LOG(info) << "Running with the B field constructed out of GRP";
112 LOG(info) << "Access field via TGeoGlobalMagField::Instance()->Field(xyz,bxyz) or via";
113 LOG(info) << "auto o2field = static_cast<o2::field::MagneticField*>( TGeoGlobalMagField::Instance()->GetField() )";
114 }
115 return 0;
116}
117
118//____________________________________________________________
119template <typename value_T>
121{
123
124 if (TGeoGlobalMagField::Instance()->IsLocked()) {
125 if (TGeoGlobalMagField::Instance()->GetField()->TestBit(o2::field::MagneticField::kOverrideGRP)) {
126 LOG(warning) << "ExpertMode!!! GRP information will be ignored";
127 LOG(warning) << "ExpertMode!!! Running with the externally locked B field";
128 return 0;
129 } else {
130 LOG(info) << "Destroying existing B field instance";
131 delete TGeoGlobalMagField::Instance();
132 }
133 }
135 TGeoGlobalMagField::Instance()->SetField(fld);
136 TGeoGlobalMagField::Instance()->Lock();
137 if (verbose) {
138 LOG(info) << "Running with the B field constructed out of GRP";
139 LOG(info) << "Access field via TGeoGlobalMagField::Instance()->Field(xyz,bxyz) or via";
140 LOG(info) << "auto o2field = static_cast<o2::field::MagneticField*>( TGeoGlobalMagField::Instance()->GetField() )";
141 }
142 return 0;
143}
144
145#elif !defined(GPUCA_GPUCODE)
146template <typename value_T>
148{
149} // empty dummy constructor for standalone benchmark
150#endif
151
152//_______________________________________________________________________
153template <typename value_T>
154GPUd() bool PropagatorImpl<value_T>::PropagateToXBxByBz(TrackParCov_t& track, value_type xToGo, value_type maxSnp, value_type maxStep,
155 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
156{
157 //----------------------------------------------------------------
158 //
159 // Propagates the track to the plane X=xk (cm)
160 // taking into account all the three components of the magnetic field
161 // and correcting for the crossed material.
162 //
163 // maxStep - maximal step for propagation
164 // tofInfo - optional container for track length and PID-dependent TOF integration
165 //
166 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
167 //----------------------------------------------------------------
168 auto dx = xToGo - track.getX();
169 int dir = dx > 0.f ? 1 : -1;
170 if (!signCorr) {
171 signCorr = -dir; // sign of eloss correction is not imposed
172 }
173
174 std::array<value_type, 3> b{};
175 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
176 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
177 if (dir < 0) {
178 step = -step;
179 }
180 auto x = track.getX() + step;
181 auto xyz0 = track.getXYZGlo();
182 getFieldXYZ(xyz0, &b[0]);
183
184 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
185 bool res = true;
186 if (matCorr != MatCorrType::USEMatCorrNONE) {
187 auto xyz1 = track.getXYZGlo();
188 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
189 if (!track.correctForMaterial(mb.meanX2X0, mb.getXRho(signCorr))) {
190 res = false;
191 }
192 if (tofInfo) {
193 tofInfo->addStep(mb.length, track.getQ2P2()); // fill L,ToF info using already calculated step length
194 tofInfo->addX2X0(mb.meanX2X0);
195 tofInfo->addXRho(mb.getXRho(signCorr));
196 }
197 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
198 auto xyz1 = track.getXYZGlo();
199 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
200 tofInfo->addStep(stepV.R(), track.getQ2P2());
201 }
202 return res;
203 };
204
205 if (!track.propagateTo(x, b)) {
206 return false;
207 }
208 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
209 correct();
210 return false;
211 }
212 if (!correct()) {
213 return false;
214 }
215 dx = xToGo - track.getX();
216 }
217 track.setX(xToGo);
218 return true;
219}
220
221//_______________________________________________________________________
222template <typename value_T>
223GPUd() bool PropagatorImpl<value_T>::PropagateToXBxByBz(TrackPar_t& track, value_type xToGo, value_type maxSnp, value_type maxStep,
224 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
225{
226 //----------------------------------------------------------------
227 //
228 // Propagates the track params to the plane X=xk (cm), NO error evaluation
229 // taking into account all the three components of the magnetic field
230 // and optionally correcting for the e.loss crossed material.
231 //
232 // maxStep - maximal step for propagation
233 // tofInfo - optional container for track length and PID-dependent TOF integration
234 //
235 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
236 //----------------------------------------------------------------
237 auto dx = xToGo - track.getX();
238 int dir = dx > 0.f ? 1 : -1;
239 if (!signCorr) {
240 signCorr = -dir; // sign of eloss correction is not imposed
241 }
242
243 std::array<value_type, 3> b{};
244 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
245 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
246 if (dir < 0) {
247 step = -step;
248 }
249 auto x = track.getX() + step;
250 auto xyz0 = track.getXYZGlo();
251 getFieldXYZ(xyz0, &b[0]);
252
253 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
254 bool res = true;
255 if (matCorr != MatCorrType::USEMatCorrNONE) {
256 auto xyz1 = track.getXYZGlo();
257 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
258 if (!track.correctForELoss(((signCorr < 0) ? -mb.length : mb.length) * mb.meanRho)) {
259 res = false;
260 }
261 if (tofInfo) {
262 tofInfo->addStep(mb.length, track.getQ2P2()); // fill L,ToF info using already calculated step length
263 tofInfo->addX2X0(mb.meanX2X0);
264 tofInfo->addXRho(mb.getXRho(signCorr));
265 }
266 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
267 auto xyz1 = track.getXYZGlo();
268 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
269 tofInfo->addStep(stepV.R(), track.getQ2P2());
270 }
271 return res;
272 };
273
274 if (!track.propagateParamTo(x, b)) {
275 return false;
276 }
277 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
278 correct();
279 return false;
280 }
281 if (!correct()) {
282 return false;
283 }
284 dx = xToGo - track.getX();
285 }
286 track.setX(xToGo);
287 return true;
288}
289
290//_______________________________________________________________________
291template <typename value_T>
292GPUd() bool PropagatorImpl<value_T>::propagateToX(TrackParCov_t& track, value_type xToGo, value_type bZ, value_type maxSnp, value_type maxStep,
293 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
294{
295 //----------------------------------------------------------------
296 //
297 // Propagates the track to the plane X=xk (cm)
298 // taking into account all the three components of the magnetic field
299 // and correcting for the crossed material.
300 //
301 // maxStep - maximal step for propagation
302 // tofInfo - optional container for track length and PID-dependent TOF integration
303 //
304 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
305 //----------------------------------------------------------------
306 auto dx = xToGo - track.getX();
307 int dir = dx > 0.f ? 1 : -1;
308 if (!signCorr) {
309 signCorr = -dir; // sign of eloss correction is not imposed
310 }
311
312 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
313 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
314 if (dir < 0) {
315 step = -step;
316 }
317 auto x = track.getX() + step;
318 auto xyz0 = track.getXYZGlo();
319 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
320 bool res = true;
321 if (matCorr != MatCorrType::USEMatCorrNONE) {
322 auto xyz1 = track.getXYZGlo();
323 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
324 if (!track.correctForMaterial(mb.meanX2X0, mb.getXRho(signCorr))) {
325 res = false;
326 }
327 if (tofInfo) {
328 tofInfo->addStep(mb.length, track.getQ2P2()); // fill L,ToF info using already calculated step length
329 tofInfo->addX2X0(mb.meanX2X0);
330 tofInfo->addXRho(mb.getXRho(signCorr));
331 }
332 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
333 auto xyz1 = track.getXYZGlo();
334 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
335 tofInfo->addStep(stepV.R(), track.getQ2P2());
336 }
337 return res;
338 };
339 if (!track.propagateTo(x, bZ)) {
340 return false;
341 }
342 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
343 correct();
344 return false;
345 }
346 if (!correct()) {
347 return false;
348 }
349 dx = xToGo - track.getX();
350 }
351 track.setX(xToGo);
352 return true;
353}
354
355//_______________________________________________________________________
356template <typename value_T>
357GPUd() bool PropagatorImpl<value_T>::propagateToX(TrackPar_t& track, value_type xToGo, value_type bZ, value_type maxSnp, value_type maxStep,
358 PropagatorImpl<value_T>::MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
359{
360 //----------------------------------------------------------------
361 //
362 // Propagates the track parameters only to the plane X=xk (cm)
363 // taking into account all the three components of the magnetic field
364 // and correcting for the crossed material.
365 //
366 // maxStep - maximal step for propagation
367 // tofInfo - optional container for track length and PID-dependent TOF integration
368 //
369 // matCorr - material correction type, it is up to the user to make sure the pointer is attached (if LUT is requested)
370 //----------------------------------------------------------------
371 auto dx = xToGo - track.getX();
372 int dir = dx > 0.f ? 1 : -1;
373 if (!signCorr) {
374 signCorr = -dir; // sign of eloss correction is not imposed
375 }
376
377 while (math_utils::detail::abs<value_type>(dx) > Epsilon) {
378 auto step = math_utils::detail::min<value_type>(math_utils::detail::abs<value_type>(dx), maxStep);
379 if (dir < 0) {
380 step = -step;
381 }
382 auto x = track.getX() + step;
383 auto xyz0 = track.getXYZGlo();
384
385 auto correct = [&track, &xyz0, tofInfo, matCorr, signCorr, this]() {
386 bool res = true;
387 if (matCorr != MatCorrType::USEMatCorrNONE) {
388 auto xyz1 = track.getXYZGlo();
389 auto mb = this->getMatBudget(matCorr, xyz0, xyz1);
390 if (!track.correctForELoss(mb.getXRho(signCorr))) {
391 res = false;
392 }
393 if (tofInfo) {
394 tofInfo->addStep(mb.length, track.getQ2P2()); // fill L,ToF info using already calculated step length
395 tofInfo->addX2X0(mb.meanX2X0);
396 tofInfo->addXRho(mb.getXRho(signCorr));
397 }
398 } else if (tofInfo) { // if tofInfo filling was requested w/o material correction, we need to calculate the step lenght
399 auto xyz1 = track.getXYZGlo();
400 math_utils::Vector3D<value_type> stepV(xyz1.X() - xyz0.X(), xyz1.Y() - xyz0.Y(), xyz1.Z() - xyz0.Z());
401 tofInfo->addStep(stepV.R(), track.getQ2P2());
402 }
403 return res;
404 };
405
406 if (!track.propagateParamTo(x, bZ)) {
407 return false;
408 }
409 if (maxSnp > 0 && math_utils::detail::abs<value_type>(track.getSnp()) >= maxSnp) {
410 correct();
411 return false;
412 }
413 if (!correct()) {
414 return false;
415 }
416 dx = xToGo - track.getX();
417 }
418 track.setX(xToGo);
419 return true;
420}
421
422//_______________________________________________________________________
423template <typename value_T>
424template <typename track_T>
425GPUd() bool PropagatorImpl<value_T>::propagateToR(track_T& track, value_type r, bool bzOnly, value_type maxSnp, value_type maxStep,
426 MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
427{
428 const value_T MaxPhiLoc = math_utils::detail::asin<value_T>(maxSnp), MaxPhiLocSafe = 0.95 * MaxPhiLoc;
429 auto bz = getNominalBz();
430 if (math_utils::detail::abs(bz) > constants::math::Almost0) {
431 o2::track::TrackAuxPar traux(track, bz);
433 value_type r0 = math_utils::detail::sqrt<value_T>(track.getX() * track.getX() + track.getY() * track.getY());
434 value_type dr = (r - r0);
435 value_type rTmp = r - (math_utils::detail::abs<value_T>(dr) > 1. ? (dr > 0 ? 0.5 : -0.5) : 0.5 * dr); // 1st propagate a few mm short of the targer R
436 crad.rC = rTmp;
437 crad.c = crad.cc = 1.f;
438 crad.s = crad.ss = crad.cs = 0.f;
440 cross.circlesCrossInfo(crad, traux, 0.);
441 if (cross.nDCA < 1) {
442 return false;
443 }
444 double phiCross[2] = {}, dphi[2] = {};
445 auto curv = track.getCurvature(bz);
446 bool clockwise = curv < 0; // q+ in B+ or q- in B- goes clockwise
447 auto phiLoc = math_utils::detail::asin<double>(track.getSnp());
448 auto phi0 = phiLoc + track.getAlpha();
450 for (int i = 0; i < cross.nDCA; i++) {
451 // track pT direction angle at crossing points:
452 // == angle of the tangential to track circle at the crossing point X,Y
453 // == normal to the radial vector from the track circle center {X-cX, Y-cY}
454 // i.e. the angle of the vector {Y-cY, -(X-cx)}
455 auto normX = double(cross.yDCA[i]) - double(traux.yC), normY = -(double(cross.xDCA[i]) - double(traux.xC));
456 if (!clockwise) {
457 normX = -normX;
458 normY = -normY;
459 }
460 phiCross[i] = math_utils::detail::atan2<double>(normY, normX);
462 dphi[i] = phiCross[i] - phi0;
463 if (dphi[i] > o2::constants::math::PI) {
465 } else if (dphi[i] < -o2::constants::math::PI) {
467 }
468 }
469 int sel = cross.nDCA == 1 ? 0 : (clockwise ? (dphi[0] < dphi[1] ? 0 : 1) : (dphi[1] < dphi[0] ? 0 : 1));
470 auto deltaPhi = dphi[sel];
471
472 while (1) {
473 auto phiLocFin = phiLoc + deltaPhi;
474 // case1
475 if (math_utils::detail::abs<value_type>(phiLocFin) < MaxPhiLocSafe) { // just 1 step propagation
476 auto deltaX = (math_utils::detail::sin<double>(phiLocFin) - track.getSnp()) / track.getCurvature(bz);
477 if (!track.propagateTo(track.getX() + deltaX, bz)) {
478 return false;
479 }
480 break;
481 }
482 if (math_utils::detail::abs<value_type>(deltaPhi) < (2 * MaxPhiLocSafe)) { // still can go in 1 step with one extra rotation
483 auto rot = phiLoc + 0.5 * deltaPhi;
484 if (!track.rotate(track.getAlpha() + rot)) {
485 return false;
486 }
487 phiLoc -= rot;
488 continue; // should be ok for the case 1 now.
489 }
490
491 auto rot = phiLoc + (deltaPhi > 0 ? MaxPhiLocSafe : -MaxPhiLocSafe);
492 if (!track.rotate(track.getAlpha() + rot)) {
493 return false;
494 }
495 phiLoc -= rot; // = +- MaxPhiLocSafe
496
497 // propagate to phiLoc = +-MaxPhiLocSafe
498 auto tgtPhiLoc = deltaPhi > 0 ? MaxPhiLocSafe : -MaxPhiLocSafe;
499 auto deltaX = (math_utils::detail::sin<double>(tgtPhiLoc) - track.getSnp()) / track.getCurvature(bz);
500 if (!track.propagateTo(track.getX() + deltaX, bz)) {
501 return false;
502 }
503 deltaPhi -= tgtPhiLoc - phiLoc;
504 phiLoc = deltaPhi > 0 ? MaxPhiLocSafe : -MaxPhiLocSafe;
505 continue; // should be of for the case 1 now.
506 }
507 bz = getBz(math_utils::Point3D<value_type>{value_type(cross.xDCA[sel]), value_type(cross.yDCA[sel]), value_type(track.getZ())});
508 }
509 // do final step till target R, also covers Bz = 0;
510 value_type xfin;
511 if (!track.getXatLabR(r, xfin, bz)) {
512 return false;
513 }
514 return propagateToX(track, xfin, bzOnly, maxSnp, maxStep, matCorr, tofInfo, signCorr);
515}
516
517//_______________________________________________________________________
518template <typename value_T>
519template <typename track_T>
520GPUd() bool PropagatorImpl<value_T>::propagateToAlphaX(track_T& track, value_type alpha, value_type x, bool bzOnly, value_type maxSnp, value_type maxStep, int minSteps,
521 MatCorrType matCorr, track::TrackLTIntegral* tofInfo, int signCorr) const
522{
523 // propagate to alpha,X, if needed in a few steps
524 auto snp = track.getSnpAt(alpha, x, getNominalBz());
525 // apply safety factor 0.9 for crude rotation estimate
526 if (math_utils::detail::abs<value_type>(snp) < maxSnp * 0.9 && track.rotate(alpha)) {
527 auto dx = math_utils::detail::abs<value_type>(x - track.getX());
528 if (dx < Epsilon) {
529 return true;
530 }
531 return propagateTo(track, x, bzOnly, maxSnp, math_utils::detail::min<value_type>(dx / minSteps, maxStep), matCorr, tofInfo, signCorr);
532 }
533 return false;
534 /*
535 // try to go in a few steps with intermediate rotations
536
537
538 auto alphaTrg = alpha;
539 math_utils::detail::bringToPMPi<value_type>(alphaTrg);
540 auto alpCurr = track.getAlpha();
541 math_utils::detail::bringToPMPi<value_type>(alpCurr);
542 int nsteps = minSteps > 2 ? minSteps : 2;
543 auto dalp = math_utils::detail::deltaPhiSmall<value_type>(alpCurr, alphaTrg) / nsteps; // effective (alpha - alphaCurr)/nsteps
544 auto xtmp = (track.getX() + x) / nsteps;
545 return track.rotate(alpCurr + dalp) && propagateTo(track, xtmp, bzOnly, maxSnp, maxStep, matCorr, tofInfo, signCorr) &&
546 track.rotate(alpha) && propagateTo(track, x, bzOnly, maxSnp, maxStep, matCorr, tofInfo, signCorr);
547 */
548}
549
550//_______________________________________________________________________
551template <typename value_T>
552GPUd() bool PropagatorImpl<value_T>::propagateToDCA(const o2::dataformats::VertexBase& vtx, TrackParCov_t& track, value_type bZ,
553 value_type maxStep, PropagatorImpl<value_type>::MatCorrType matCorr,
554 o2::dataformats::DCA* dca, track::TrackLTIntegral* tofInfo,
555 int signCorr, value_type maxD) const
556{
557 // propagate track to DCA to the vertex
558 value_type sn, cs, alp = track.getAlpha();
559 math_utils::detail::sincos<value_type>(alp, sn, cs);
560 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
561 value_type xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ();
562 x -= xv;
563 y -= yv;
564 // Estimate the impact parameter neglecting the track curvature
565 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
566 if (d > maxD) {
567 if (dca) { // provide default DCA for failed propag
570 }
571 return false;
572 }
573 value_type crv = track.getCurvature(bZ);
574 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
575 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
576 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
577 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
578
579 x = xv * cs + yv * sn;
580 yv = -xv * sn + yv * cs;
581 xv = x;
582
583 auto tmpT(track); // operate on the copy to recover after the failure
584 alp += math_utils::detail::asin<value_type>(sn);
585 if (!tmpT.rotate(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
586#ifndef GPUCA_ALIGPUCODE
587 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: " << tmpT.asString();
588#elif !defined(GPUCA_NO_FMT)
589 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx;
590#endif
591 if (dca) { // provide default DCA for failed propag
594 }
595 return false;
596 }
597 track = tmpT;
598 if (dca) {
599 math_utils::detail::sincos<value_type>(alp, sn, cs);
600 auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn;
601 dca->set(track.getY() - yv, track.getZ() - zv,
602 track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2());
603 }
604 return true;
605}
606
607//_______________________________________________________________________
608template <typename value_T>
609GPUd() bool PropagatorImpl<value_T>::propagateToDCABxByBz(const o2::dataformats::VertexBase& vtx, TrackParCov_t& track,
610 value_type maxStep, PropagatorImpl<value_type>::MatCorrType matCorr,
611 o2::dataformats::DCA* dca, track::TrackLTIntegral* tofInfo,
612 int signCorr, value_type maxD) const
613{
614 // propagate track to DCA to the vertex
615 value_type sn, cs, alp = track.getAlpha();
616 math_utils::detail::sincos<value_type>(alp, sn, cs);
617 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
618 value_type xv = vtx.getX() * cs + vtx.getY() * sn, yv = -vtx.getX() * sn + vtx.getY() * cs, zv = vtx.getZ();
619 x -= xv;
620 y -= yv;
621 // Estimate the impact parameter neglecting the track curvature
622 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
623 if (d > maxD) {
624 if (dca) { // provide default DCA for failed propag
627 }
628 return false;
629 }
630 value_type crv = track.getCurvature(mNominalBz);
631 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
632 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
633 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
634 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
635
636 x = xv * cs + yv * sn;
637 yv = -xv * sn + yv * cs;
638 xv = x;
639
640 auto tmpT(track); // operate on the copy to recover after the failure
641 alp += math_utils::detail::asin<value_type>(sn);
642 if (!tmpT.rotate(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
643#ifndef GPUCA_ALIGPUCODE
644 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx << " | Track is: " << tmpT.asString();
645#elif !defined(GPUCA_NO_FMT)
646 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << vtx;
647#endif
648 if (dca) { // provide default DCA for failed propag
651 }
652 return false;
653 }
654 track = tmpT;
655 if (dca) {
656 math_utils::detail::sincos<value_type>(alp, sn, cs);
657 auto s2ylocvtx = vtx.getSigmaX2() * sn * sn + vtx.getSigmaY2() * cs * cs - 2. * vtx.getSigmaXY() * cs * sn;
658 dca->set(track.getY() - yv, track.getZ() - zv,
659 track.getSigmaY2() + s2ylocvtx, track.getSigmaZY(), track.getSigmaZ2() + vtx.getSigmaZ2());
660 }
661 return true;
662}
663
664//_______________________________________________________________________
665template <typename value_T>
666GPUd() bool PropagatorImpl<value_T>::propagateToDCA(const math_utils::Point3D<value_type>& vtx, TrackPar_t& track, value_type bZ,
667 value_type maxStep, PropagatorImpl<value_T>::MatCorrType matCorr,
668 std::array<value_type, 2>* dca, track::TrackLTIntegral* tofInfo,
669 int signCorr, value_type maxD) const
670{
671 // propagate track to DCA to the vertex
672 value_type sn, cs, alp = track.getAlpha();
673 math_utils::detail::sincos<value_type>(alp, sn, cs);
674 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
675 value_type xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
676 x -= xv;
677 y -= yv;
678 // Estimate the impact parameter neglecting the track curvature
679 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
680 if (d > maxD) {
681 if (dca) { // provide default DCA for failed propag
682 (*dca)[0] = o2::track::DefaultDCA;
683 (*dca)[1] = o2::track::DefaultDCA;
684 }
685 return false;
686 }
687 value_type crv = track.getCurvature(bZ);
688 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
689 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
690 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
691 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
692
693 x = xv * cs + yv * sn;
694 yv = -xv * sn + yv * cs;
695 xv = x;
696
697 auto tmpT(track); // operate on the copy to recover after the failure
698 alp += math_utils::detail::asin<value_type>(sn);
699 if (!tmpT.rotateParam(alp) || !propagateToX(tmpT, xv, bZ, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
700#ifndef GPUCA_ALIGPUCODE
701 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex "
702 << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: " << tmpT.asString();
703#else
704 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z();
705#endif
706 if (dca) { // provide default DCA for failed propag
707 (*dca)[0] = o2::track::DefaultDCA;
708 (*dca)[1] = o2::track::DefaultDCA;
709 }
710 return false;
711 }
712 track = tmpT;
713 if (dca) {
714 (*dca)[0] = track.getY() - yv;
715 (*dca)[1] = track.getZ() - zv;
716 }
717 return true;
718}
719
720//_______________________________________________________________________
721template <typename value_T>
722GPUd() bool PropagatorImpl<value_T>::propagateToDCABxByBz(const math_utils::Point3D<value_type>& vtx, TrackPar_t& track,
723 value_type maxStep, PropagatorImpl<value_T>::MatCorrType matCorr,
724 std::array<value_type, 2>* dca, track::TrackLTIntegral* tofInfo,
725 int signCorr, value_type maxD) const
726{
727 // propagate track to DCA to the vertex
728 value_type sn, cs, alp = track.getAlpha();
729 math_utils::detail::sincos<value_type>(alp, sn, cs);
730 value_type x = track.getX(), y = track.getY(), snp = track.getSnp(), csp = math_utils::detail::sqrt<value_type>((1.f - snp) * (1.f + snp));
731 value_type xv = vtx.X() * cs + vtx.Y() * sn, yv = -vtx.X() * sn + vtx.Y() * cs, zv = vtx.Z();
732 x -= xv;
733 y -= yv;
734 // Estimate the impact parameter neglecting the track curvature
735 value_type d = math_utils::detail::abs<value_type>(x * snp - y * csp);
736 if (d > maxD) {
737 if (dca) { // provide default DCA for failed propag
738 (*dca)[0] = o2::track::DefaultDCA;
739 (*dca)[1] = o2::track::DefaultDCA;
740 }
741 return false;
742 }
743 value_type crv = track.getCurvature(mNominalBz);
744 value_type tgfv = -(crv * x - snp) / (crv * y + csp);
745 sn = tgfv / math_utils::detail::sqrt<value_type>(1.f + tgfv * tgfv);
746 cs = math_utils::detail::sqrt<value_type>((1. - sn) * (1. + sn));
747 cs = (math_utils::detail::abs<value_type>(tgfv) > o2::constants::math::Almost0) ? sn / tgfv : o2::constants::math::Almost1;
748
749 x = xv * cs + yv * sn;
750 yv = -xv * sn + yv * cs;
751 xv = x;
752
753 auto tmpT(track); // operate on the copy to recover after the failure
754 alp += math_utils::detail::asin<value_type>(sn);
755 if (!tmpT.rotateParam(alp) || !PropagateToXBxByBz(tmpT, xv, 0.85, maxStep, matCorr, tofInfo, signCorr)) {
756#ifndef GPUCA_ALIGPUCODE
757 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex "
758 << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z() << " | Track is: " << tmpT.asString();
759#else
760 LOG(debug) << "failed to propagate to alpha=" << alp << " X=" << xv << " for vertex " << vtx.X() << ' ' << vtx.Y() << ' ' << vtx.Z();
761#endif
762 if (dca) { // provide default DCA for failed propag
763 (*dca)[0] = o2::track::DefaultDCA;
764 (*dca)[1] = o2::track::DefaultDCA;
765 }
766 return false;
767 }
768 track = tmpT;
769 if (dca) {
770 (*dca)[0] = track.getY() - yv;
771 (*dca)[1] = track.getZ() - zv;
772 }
773 return true;
774}
775
776//____________________________________________________________
777template <typename value_T>
778GPUd() float PropagatorImpl<value_T>::estimateLTIncrement(const o2::track::TrackParametrization<value_type>& trc,
779 const o2::math_utils::Point3D<value_type>& posStart,
780 const o2::math_utils::Point3D<value_type>& posEnd) const
781{
782 // estimate helical step increment between 2 point
783 float dX = posEnd.X() - posStart.X(), dY = posEnd.Y() - posStart.Y(), dZ = posEnd.Z() - posStart.Z(), d2XY = dX * dX + dY * dY;
784 if (getNominalBz() != 0) { // circular arc = 2*R*asin(dXY/2R)
785 float b[3];
786 o2::math_utils::Point3D<float> posAv(0.5 * (posEnd.X() + posStart.X()), 0.5 * (posEnd.Y() + posStart.Y()), 0.5 * (posEnd.Z() + posStart.Z()));
787 getFieldXYZ(posAv, b);
788 float curvH = math_utils::detail::abs<value_type>(0.5f * trc.getCurvature(b[2])), asArg = curvH * math_utils::detail::sqrt<value_type>(d2XY);
789 if (curvH > 0.f) {
790 d2XY = asArg < 1.f ? math_utils::detail::asin<value_type>(asArg) / curvH : o2::constants::math::PIHalf / curvH;
791 d2XY *= d2XY;
792 }
793 }
794 return math_utils::detail::sqrt<value_type>(d2XY + dZ * dZ);
795}
796
797//____________________________________________________________
798template <typename value_T>
799GPUd() value_T PropagatorImpl<value_T>::estimateLTFast(o2::track::TrackLTIntegral& lt, const o2::track::TrackParametrization<value_type>& trc) const
800{
801 value_T xdca = 0., ydca = 0., length = 0.; // , zdca = 0. // zdca might be used in future
803 constexpr float TinyF = 1e-9;
804 auto straigh_line_approx = [&]() {
805 auto csp2 = (1.f - trc.getSnp()) * (1.f + trc.getSnp());
806 if (csp2 > TinyF) {
807 auto csp = math_utils::detail::sqrt<value_type>(csp2);
808 auto tgp = trc.getSnp() / csp, f = trc.getX() * tgp - trc.getY();
809 xdca = tgp * f * csp2;
810 ydca = -f * csp2;
811 auto dx = xdca - trc.getX(), dy = ydca - trc.getY(), dz = dx * trc.getTgl() / csp;
812 return math_utils::detail::sqrt<value_type>(dx * dx + dy * dy + dz * dz);
813 } else { // track is parallel to Y axis
814 xdca = trc.getX(); // ydca = 0
815 return math_utils::detail::abs<value_type>(trc.getY() * math_utils::detail::sqrt<value_type>(1. + trc.getTgl() * trc.getTgl())); // distance from the current point to DCA
816 }
817 };
818 trc.getCircleParamsLoc(mNominalBz, c);
819 if (c.rC != 0.) { // helix
820 auto distC = math_utils::detail::sqrt<value_type>(c.getCenterD2()); // distance from the circle center to origin
821 if (distC > 1.e-3) {
822 auto nrm = (distC - c.rC) / distC;
823 xdca = nrm * c.xC; // coordinates of the DCA to 0,0 in the local frame
824 ydca = nrm * c.yC;
825 auto v0x = trc.getX() - c.xC, v0y = trc.getY() - c.yC, v1x = xdca - c.xC, v1y = ydca - c.yC;
826 auto angcos = (v0x * v1x + v0y * v1y) / (c.rC * c.rC);
827 if (math_utils::detail::abs<value_type>(angcos) < 1.f) {
828 auto ang = math_utils::detail::acos<value_type>(angcos);
829 if ((trc.getSign() > 0.f) == (mNominalBz > 0.f)) {
830 ang = -ang; // we need signeg angle
831 c.rC = -c.rC; // we need signed curvature for zdca
832 }
833 // zdca = trc.getZ() + (trc.getSign() > 0. ? c.rC : -c.rC) * trc.getTgl() * ang;
834 length = math_utils::detail::abs<value_type>(c.rC * ang * math_utils::detail::sqrt<value_type>(1. + trc.getTgl() * trc.getTgl()));
835 } else { // calculation of the arc length between the position and DCA makes no sense
836 length = straigh_line_approx();
837 }
838 } else { // track with circle center at the origin, and LT makes no sense, take direct distance
839 xdca = trc.getX();
840 ydca = trc.getY();
841 }
842 } else { // straight line
843 length = straigh_line_approx();
844 }
845 // since we assume the track or its parent comes from the beam-line or decay, add XY(?) distance to it
846 value_T dcaT = math_utils::detail::sqrt<value_type>(xdca * xdca + ydca * ydca);
847 length += dcaT;
848 lt.addStep(length, trc.getQ2P2());
849 return dcaT;
850}
851
852//____________________________________________________________
853template <typename value_T>
854GPUd() MatBudget PropagatorImpl<value_T>::getMatBudget(PropagatorImpl<value_type>::MatCorrType corrType, const math_utils::Point3D<value_type>& p0, const math_utils::Point3D<value_type>& p1) const
855{
856#if !defined(GPUCA_STANDALONE) && !defined(GPUCA_GPUCODE)
857 if (corrType == MatCorrType::USEMatCorrTGeo) {
859 }
860 if (!mMatLUT) {
861 if (mTGeoFallBackAllowed) {
863 } else {
864 throw std::runtime_error("requested MatLUT is absent and fall-back to TGeo is disabled");
865 }
866 }
867#endif
868 return mMatLUT->getMatBudget(p0.X(), p0.Y(), p0.Z(), p1.X(), p1.Y(), p1.Z());
869}
870
871template <typename value_T>
872template <typename T>
873GPUd() void PropagatorImpl<value_T>::getFieldXYZImpl(const math_utils::Point3D<T> xyz, T* bxyz) const
874{
875 if (mGPUField) {
876#if defined(GPUCA_GPUCODE_DEVICE) && defined(GPUCA_HAS_GLOBAL_SYMBOL_CONSTANT_MEM)
877 const auto* f = &GPUCA_CONSMEM.param.polynomialField; // Access directly from constant memory on GPU (copied here to avoid complicated header dependencies)
878#else
879 const auto* f = mGPUField;
880#endif
881 float bxyzF[3] = {};
882 f->GetField(xyz.X(), xyz.Y(), xyz.Z(), bxyzF);
883 // copy and convert
884 constexpr value_type kCLight1 = 1. / o2::gpu::gpu_common_constants::kCLight;
885 for (uint i = 0; i < 3; ++i) {
886 bxyz[i] = static_cast<value_type>(bxyzF[i]) * kCLight1;
887 }
888 } else {
889#ifndef GPUCA_GPUCODE
890 if (mFieldFast) {
891 mFieldFast->Field(xyz, bxyz); // Must not call the host-only function in GPU compilation
892 } else {
893#ifdef GPUCA_STANDALONE
894 LOG(fatal) << "Normal field cannot be used in standalone benchmark";
895#else
896 mField->field(xyz, bxyz);
897#endif
898 }
899#endif
900 }
901}
902
903template <typename value_T>
904template <typename T>
905GPUd() T PropagatorImpl<value_T>::getBzImpl(const math_utils::Point3D<T> xyz) const
906{
907 T bz = 0;
908 if (mGPUField) {
909#if defined(GPUCA_GPUCODE_DEVICE) && defined(GPUCA_HAS_GLOBAL_SYMBOL_CONSTANT_MEM)
910 const auto* f = &GPUCA_CONSMEM.param.polynomialField; // Access directly from constant memory on GPU (copied here to avoid complicated header dependencies)
911#else
912 const auto* f = mGPUField;
913#endif
914 constexpr value_type kCLight1 = 1. / o2::gpu::gpu_common_constants::kCLight;
915 bz = f->GetFieldBz(xyz.X(), xyz.Y(), xyz.Z()) * kCLight1;
916 } else {
917#ifndef GPUCA_GPUCODE
918 if (mFieldFast) {
919 mFieldFast->GetBz(xyz, bz); // Must not call the host-only function in GPU compilation
920 } else {
921#ifdef GPUCA_STANDALONE
922 LOG(fatal) << "Normal field cannot be used in standalone benchmark";
923#else
924 bz = mField->GetBz(xyz.X(), xyz.Y(), xyz.Z());
925#endif
926 }
927#endif
928 }
929 return bz;
930}
931
932template <typename value_T>
933GPUd() void PropagatorImpl<value_T>::getFieldXYZ(const math_utils::Point3D<float> xyz, float* bxyz) const
934{
935 getFieldXYZImpl<float>(xyz, bxyz);
936}
937
938template <typename value_T>
939GPUd() void PropagatorImpl<value_T>::getFieldXYZ(const math_utils::Point3D<double> xyz, double* bxyz) const
940{
941 getFieldXYZImpl<double>(xyz, bxyz);
942}
943
944template <typename value_T>
945GPUd() float PropagatorImpl<value_T>::getBz(const math_utils::Point3D<float> xyz) const
946{
947 return getBzImpl<float>(xyz);
948}
949
950template <typename value_T>
951GPUd() double PropagatorImpl<value_T>::getBz(const math_utils::Point3D<double> xyz) const
952{
953 return getBzImpl<double>(xyz);
954}
955
956namespace o2::base
957{
958#if !defined(GPUCA_GPUCODE) || defined(GPUCA_GPUCODE_DEVICE) // FIXME: DR: WORKAROUND to avoid CUDA bug creating host symbols for device code.
959template class PropagatorImpl<float>;
960template bool GPUdni() PropagatorImpl<float>::propagateToAlphaX<PropagatorImpl<float>::TrackPar_t>(PropagatorImpl<float>::TrackPar_t&, float, float, bool, float, float, int, PropagatorImpl<float>::MatCorrType matCorr, track::TrackLTIntegral*, int) const;
961template bool GPUdni() PropagatorImpl<float>::propagateToAlphaX<PropagatorImpl<float>::TrackParCov_t>(PropagatorImpl<float>::TrackParCov_t&, float, float, bool, float, float, int, PropagatorImpl<float>::MatCorrType matCorr, track::TrackLTIntegral*, int) const;
962template bool GPUdni() PropagatorImpl<float>::propagateToR<PropagatorImpl<float>::TrackPar_t>(PropagatorImpl<float>::TrackPar_t&, float, bool, float, float, PropagatorImpl<float>::MatCorrType matCorr, track::TrackLTIntegral*, int) const;
963template bool GPUdni() PropagatorImpl<float>::propagateToR<PropagatorImpl<float>::TrackParCov_t>(PropagatorImpl<float>::TrackParCov_t&, float, bool, float, float, PropagatorImpl<float>::MatCorrType matCorr, track::TrackLTIntegral*, int) const;
964#endif
965#ifndef GPUCA_GPUCODE
966template class PropagatorImpl<double>;
969#endif
970} // namespace o2::base
General auxilliary methods.
Definition of the GeometryManager class.
int32_t i
#define GPUdni()
#define GPUCA_CONSMEM
Header of the General Run Parameters object for B field values.
Header of the General Run Parameters object.
Helper classes for helical tracks manipulations.
constexpr int p1()
constexpr to accelerate the coordinates changing
Definition of the fast magnetic field parametrization MagFieldFast.
Definition of the MagF class.
uint32_t res
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
std::ostringstream debug
static o2::base::MatBudget meanMaterialBudget(float x0, float y0, float z0, float x1, float y1, float z1)
GPUd() bool propagateToDCA(const o2 GPUd() bool propagateToDCABxByBz(const o2 GPUd() bool propagateToDCA(const o2 GPUd() bool propagateToDCABxByBz(const o2 PropagatorImpl(PropagatorImpl const &)=delete
static int initFieldFromGRP(const o2::parameters::GRPMagField *grp, bool verbose=false)
static MagneticField * createFieldMap(float l3Current=-30000., float diCurrent=-6000., Int_t convention=0, Bool_t uniform=kFALSE, float beamenergy=7000, const Char_t *btype="pp", const std::string path=std::string(gSystem->Getenv("VMCWORKDIR"))+std::string("/Common/maps/mfchebKGI_sym.root"))
void AllowFastField(bool v=true)
allow fast field param
o2::units::Current_t getDipoleCurrent() const
Definition GRPMagField.h:43
bool getFieldUniformity() const
Definition GRPMagField.h:49
o2::units::Current_t getL3Current() const
getters/setters for magnets currents
Definition GRPMagField.h:37
o2::units::Current_t getDipoleCurrent() const
Definition GRPObject.h:80
bool getFieldUniformity() const
Definition GRPObject.h:81
static GRPObject * loadFrom(const std::string &grpFileName="")
o2::units::Current_t getL3Current() const
getters/setters for magnets currents
Definition GRPObject.h:79
GLfloat GLfloat GLfloat alpha
Definition glcorearb.h:279
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum array
Definition glcorearb.h:4274
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean r
Definition glcorearb.h:1233
constexpr float Almost0
constexpr float TwoPI
constexpr float PI
constexpr float PIHalf
constexpr float Almost1
GPUd() const expr uint32_t MultivariatePolynomialHelper< Dim
std::array< int, 24 > p0
value_T step
Definition TrackUtils.h:42
constexpr float DefaultDCACov
constexpr float DefaultDCA
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"