99// granted to it by virtue of its status as an Intergovernmental Organization
1010// or submit itself to any jurisdiction.
1111
12- #include < vector>
13- #include < string>
12+ #include " FastTracker.h"
13+
14+ #include " ReconstructionDataFormats/TrackParametrization.h"
15+
1416#include " TMath.h"
1517#include " TMatrixD.h"
16- #include " TRandom.h"
1718#include " TMatrixDSymEigen.h"
18- #include " FastTracker.h"
19+ #include " TRandom.h"
20+
21+ #include < string>
22+ #include < vector>
1923
2024namespace o2
2125{
@@ -24,43 +28,24 @@ namespace fastsim
2428
2529// +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+
2630
27- FastTracker::FastTracker ()
28- {
29- // base constructor
30- magneticField = 20 ; // in kiloGauss
31- applyZacceptance = false ;
32- applyMSCorrection = true ;
33- applyElossCorrection = true ;
34- applyEffCorrection = true ;
35- covMatFactor = 0 .99f ;
36- verboseLevel = 0 ;
37-
38- // last fast-tracked track properties
39- covMatOK = 0 ;
40- covMatNotOK = 0 ;
41- nIntercepts = 0 ;
42- nSiliconPoints = 0 ;
43- nGasPoints = 0 ;
44-
45- maxRadiusSlowDet = 10 ;
46- integrationTime = 0.02 ; // ms
47- crossSectionMinB = 8 ;
48- dNdEtaCent = 2200 ;
49- dNdEtaMinB = 1 ;
50- avgRapidity = 0.45 ;
51- sigmaD = 6.0 ;
52- luminosity = 1 .e27 ;
53- otherBackground = 0.0 ; // [0, 1]
54- upcBackgroundMultiplier = 1.0 ;
55- }
56-
5731void FastTracker::AddLayer (TString name, float r, float z, float x0, float xrho, float resRPhi, float resZ, float eff, int type)
5832{
5933 DetLayer newLayer (name, r, z, x0, xrho, resRPhi, resZ, eff, type);
6034 // Check that efficient layers are not inert layers
6135 if (newLayer.getEfficiency () > 0 .0f && newLayer.isInert ()) {
6236 LOG (error) << " Layer " << name << " with efficiency > 0.0 should not be inert" ;
6337 }
38+ // Layers should be ordered by increasing radius, check this
39+ if (!layers.empty () && newLayer.getRadius () < layers.back ().getRadius ()) {
40+ LOG (fatal) << " Layer " << newLayer << " is not ordered correctly, it should be after layer " << layers.back ();
41+ }
42+ // Layers should all have different names
43+ for (const auto & layer : layers) {
44+ if (layer.getName () == newLayer.getName ()) {
45+ LOG (fatal) << " Layer with name " << newLayer.getName () << " already exists in FastTracker layers" ;
46+ }
47+ }
48+ // Add the new layer to the layers vector
6449 layers.push_back (newLayer);
6550}
6651
@@ -78,7 +63,7 @@ DetLayer FastTracker::GetLayer(int layer, bool ignoreBarrelLayers) const
7863 return layers[layerIdx];
7964}
8065
81- int FastTracker::GetLayerIndex (std::string name) const
66+ int FastTracker::GetLayerIndex (const std::string& name) const
8267{
8368 int i = 0 ;
8469 for (const auto & layer : layers) {
@@ -211,9 +196,9 @@ float FastTracker::Dist(float z, float r)
211196 // https://github.com/AliceO2Group/DelphesO2/blob/master/src/DetectorK/DetectorK.cxx#L743
212197 int index = 1 ;
213198 int nSteps = 301 ;
214- double dist = 0.0 ;
215- double dz0 = (4 * sigmaD - (-4 ) * sigmaD / (nSteps = 1 ));
216- double z0 = 0.0 ;
199+ float dist = 0.0 ;
200+ float dz0 = (4 * sigmaD - (-4 ) * sigmaD / (nSteps = 1 ));
201+ float z0 = 0.0 ;
217202 for (int i = 0 ; i < nSteps; i++) {
218203 if (i == nSteps - 1 )
219204 index = 1 ;
@@ -243,7 +228,7 @@ float FastTracker::IntegratedHitDensity(float multiplicity, float radius)
243228 // porting of DetektorK::IntegratedHitDensity
244229 // see here:
245230 // https://github.com/AliceO2Group/DelphesO2/blob/master/src/DetectorK/DetectorK.cxx#L712
246- float zdcHz = luminosity * 1 .e24 * crossSectionMinB ;
231+ float zdcHz = luminosity * 1 .e24 * mCrossSectionMinB ;
247232 float den = zdcHz * integrationTime / 1000 . * multiplicity * Dist (0 ., radius) / (o2::constants::math::TwoPI * radius);
248233 if (den < OneEventHitDensity (multiplicity, radius))
249234 den = OneEventHitDensity (multiplicity, radius);
@@ -301,6 +286,7 @@ float FastTracker::ProbGoodChiSqHit(float radius, float searchRadiusRPhi, float
301286// returns number of intercepts (generic for now)
302287int FastTracker::FastTrack (o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch)
303288{
289+ dNdEtaCent = nch; // set the number of charged particles per unit rapidity
304290 hits.clear ();
305291 nIntercepts = 0 ;
306292 nSiliconPoints = 0 ;
@@ -310,38 +296,54 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
310296 const float initialRadius = std::hypot (posIni[0 ], posIni[1 ]);
311297 const float kTrackingMargin = 0.1 ;
312298 const int kMaxNumberOfDetectors = 20 ;
299+ if (kMaxNumberOfDetectors < layers.size ()) {
300+ LOG (fatal) << " Too many layers in FastTracker, increase kMaxNumberOfDetectors" ;
301+ return -1 ; // too many layers
302+ }
303+ int firstActiveLayer = -1 ; // first layer that is not inert
304+ for (size_t i = 0 ; i < layers.size (); ++i) {
305+ if (!layers[i].isInert ()) {
306+ firstActiveLayer = i;
307+ break ;
308+ }
309+ }
310+ if (firstActiveLayer <= 0 ) {
311+ LOG (fatal) << " No active layers found in FastTracker, check layer setup" ;
312+ return -2 ; // no active layers
313+ }
313314 const int xrhosteps = 100 ;
314315 const bool applyAngularCorrection = true ;
315316
316317 goodHitProbability.clear ();
317- for (int i = 0 ; i < kMaxNumberOfDetectors ; ++i)
318+ for (int i = 0 ; i < kMaxNumberOfDetectors ; ++i) {
318319 goodHitProbability.push_back (-1 .);
319- goodHitProbability[0 ] = 1 .;
320+ }
321+ goodHitProbability[0 ] = 1 .; // we use layer zero to accumulate
320322
321323 // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+
322324 // Outward pass to find intercepts
323325 int firstLayerReached = -1 ;
324326 int lastLayerReached = -1 ;
325327 new (&outputTrack)(o2::track::TrackParCov)(inputTrack);
326- for (uint32_t il = 0 ; il < layers.size (); il++) {
328+ for (size_t il = 0 ; il < layers.size (); il++) {
327329 // check if layer is doable
328- if (layers[il].getRadius () < initialRadius)
330+ if (layers[il].getRadius () < initialRadius) {
329331 continue ; // this layer should not be attempted, but go ahead
332+ }
330333
331334 // check if layer is reached
332335 float targetX = 1e+3 ;
333- bool ok = true ;
334336 inputTrack.getXatLabR (layers[il].getRadius (), targetX, magneticField);
335337 if (targetX > 999 .f ) {
336338 LOGF (debug, " Failed to find intercept for layer %d at radius %.2f cm" , il, layers[il].getRadius ());
337339 break ; // failed to find intercept
338340 }
339341
340- ok = inputTrack.propagateTo (targetX, magneticField);
341- if (ok && applyMSCorrection && layers[il].getRadiationLength () > 0 ) {
342+ bool ok = inputTrack.propagateTo (targetX, magneticField);
343+ if (ok && mApplyMSCorrection && layers[il].getRadiationLength () > 0 ) {
342344 ok = inputTrack.correctForMaterial (layers[il].getRadiationLength (), 0 , applyAngularCorrection);
343345 }
344- if (ok && applyElossCorrection && layers[il].getDensity () > 0 ) { // correct in small steps
346+ if (ok && mApplyElossCorrection && layers[il].getDensity () > 0 ) { // correct in small steps
345347 for (int ise = xrhosteps; ise--;) {
346348 ok = inputTrack.correctForMaterial (0 , -layers[il].getDensity () / xrhosteps, applyAngularCorrection);
347349 if (!ok)
@@ -361,7 +363,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
361363 break ;
362364 }
363365 }
364- if (std::abs (inputTrack.getZ ()) > layers[il].getZ () && applyZacceptance ) {
366+ if (std::abs (inputTrack.getZ ()) > layers[il].getZ () && mApplyZacceptance ) {
365367 break ; // out of acceptance bounds
366368 }
367369
@@ -384,39 +386,19 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
384386 o2::track::TrackParCov inwardTrack (inputTrack);
385387
386388 // Enlarge covariance matrix
387- std::array<float , 5 > trPars = {0 .};
388- for (int ip = 0 ; ip < 5 ; ip++) {
389+ std::array<float , o2::track:: kNParams > trPars = {0 .};
390+ for (int ip = 0 ; ip < o2::track:: kNParams ; ip++) {
389391 trPars[ip] = outputTrack.getParam (ip);
390392 }
391- std::array<float , 15 > largeCov = {0 .};
392- enum { kY ,
393- kZ ,
394- kSnp ,
395- kTgl ,
396- kPtI }; // track parameter aliases
397- enum { kY2 ,
398- kYZ ,
399- kZ2 ,
400- kYSnp ,
401- kZSnp ,
402- kSnp2 ,
403- kYTgl ,
404- kZTgl ,
405- kSnpTgl ,
406- kTgl2 ,
407- kYPtI ,
408- kZPtI ,
409- kSnpPtI ,
410- kTglPtI ,
411- kPtI2 }; // cov.matrix aliases
412- const double kLargeErr2Coord = 5 * 5 ;
413- const double kLargeErr2Dir = 0.7 * 0.7 ;
414- const double kLargeErr2PtI = 30.5 * 30.5 ;
415- for (int ic = 15 ; ic--;)
393+ static constexpr float kLargeErr2Coord = 5 * 5 ;
394+ static constexpr float kLargeErr2Dir = 0.7 * 0.7 ;
395+ static constexpr float kLargeErr2PtI = 30.5 * 30.5 ;
396+ std::array<float , o2::track::kCovMatSize > largeCov = {0 .};
397+ for (int ic = o2::track::kCovMatSize ; ic--;)
416398 largeCov[ic] = 0 .;
417- largeCov[kY2 ] = largeCov[kZ2 ] = kLargeErr2Coord ;
418- largeCov[kSnp2 ] = largeCov[kTgl2 ] = kLargeErr2Dir ;
419- largeCov[kPtI2 ] = kLargeErr2PtI * trPars[kPtI ] * trPars[kPtI ];
399+ largeCov[o2::track::CovLabels:: kSigY2 ] = largeCov[o2::track::CovLabels:: kSigZ2 ] = kLargeErr2Coord ;
400+ largeCov[o2::track::CovLabels:: kSigSnp2 ] = largeCov[o2::track::CovLabels:: kSigTgl2 ] = kLargeErr2Dir ;
401+ largeCov[o2::track::CovLabels:: kSigQ2Pt2 ] = kLargeErr2PtI * trPars[o2::track::ParLabels:: kQ2Pt ] * trPars[o2::track::ParLabels:: kQ2Pt ];
420402
421403 inwardTrack.setCov (largeCov);
422404 inwardTrack.checkCovariance ();
@@ -434,7 +416,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
434416 continue ; // failed to propagate
435417 }
436418
437- if (std::abs (inputTrack.getZ ()) > layers[il].getZ () && applyZacceptance ) {
419+ if (std::abs (inputTrack.getZ ()) > layers[il].getZ () && mApplyZacceptance ) {
438420 continue ; // out of acceptance bounds but continue inwards
439421 }
440422
@@ -444,10 +426,10 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
444426 std::vector<float > thisHit = {spacePoint[0 ], spacePoint[1 ], spacePoint[2 ]};
445427
446428 // towards adding cluster: move to track alpha
447- double alpha = inwardTrack.getAlpha ();
448- double xyz1[3 ]{
449- TMath::Cos (alpha) * spacePoint[0 ] + TMath::Sin (alpha) * spacePoint[1 ],
450- -TMath::Sin (alpha) * spacePoint[0 ] + TMath::Cos (alpha) * spacePoint[1 ],
429+ float alpha = inwardTrack.getAlpha ();
430+ float xyz1[3 ]{
431+ std::cos (alpha) * spacePoint[0 ] + std::sin (alpha) * spacePoint[1 ],
432+ -std::sin (alpha) * spacePoint[0 ] + std::cos (alpha) * spacePoint[1 ],
451433 spacePoint[2 ]};
452434 if (!inwardTrack.propagateTo (xyz1[0 ], magneticField))
453435 continue ;
@@ -462,15 +444,15 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
462444 inwardTrack.checkCovariance ();
463445 }
464446
465- if (applyMSCorrection && layers[il].getRadiationLength () > 0 ) {
447+ if (mApplyMSCorrection && layers[il].getRadiationLength () > 0 ) {
466448 if (!inputTrack.correctForMaterial (layers[il].getRadiationLength (), 0 , applyAngularCorrection)) {
467449 return -6 ;
468450 }
469451 if (!inwardTrack.correctForMaterial (layers[il].getRadiationLength (), 0 , applyAngularCorrection)) {
470452 return -6 ;
471453 }
472454 }
473- if (applyElossCorrection && layers[il].getDensity () > 0 ) {
455+ if (mApplyElossCorrection && layers[il].getDensity () > 0 ) {
474456 for (int ise = xrhosteps; ise--;) { // correct in small steps
475457 if (!inputTrack.correctForMaterial (0 , layers[il].getDensity () / xrhosteps, applyAngularCorrection)) {
476458 return -7 ;
@@ -488,19 +470,21 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
488470
489471 hits.push_back (thisHit);
490472
491- if (applyEffCorrection && !layers[il].isInert ()) { // good hit probability calculation
492- double sigYCmb = o2::math_utils::sqrt (inwardTrack.getSigmaY2 () + layers[il].getResolutionRPhi () * layers[il].getResolutionRPhi ());
493- double sigZCmb = o2::math_utils::sqrt (inwardTrack.getSigmaZ2 () + layers[il].getResolutionZ () * layers[il].getResolutionZ ());
473+ if (!layers[il].isInert ()) { // good hit probability calculation
474+ float sigYCmb = o2::math_utils::sqrt (inwardTrack.getSigmaY2 () + layers[il].getResolutionRPhi () * layers[il].getResolutionRPhi ());
475+ float sigZCmb = o2::math_utils::sqrt (inwardTrack.getSigmaZ2 () + layers[il].getResolutionZ () * layers[il].getResolutionZ ());
494476 goodHitProbability[il] = ProbGoodChiSqHit (layers[il].getRadius () * 100 , sigYCmb * 100 , sigZCmb * 100 );
495477 goodHitProbability[0 ] *= goodHitProbability[il];
496478 }
497479 }
498480
499481 // backpropagate to original radius
500482 float finalX = 1e+3 ;
501- inwardTrack.getXatLabR (initialRadius, finalX, magneticField);
502- if (finalX > 999 )
483+ bool inPropStatus = inwardTrack.getXatLabR (initialRadius, finalX, magneticField);
484+ if (finalX > 999 ) {
485+ LOG (debug) << " Failed to find intercept for initial radius " << initialRadius << " cm, x = " << finalX << " and status " << inPropStatus << " and sn = " << inwardTrack.getSnp () << " r = " << inwardTrack.getY () * inwardTrack.getY ();
503486 return -3 ; // failed to find intercept
487+ }
504488
505489 if (!inwardTrack.propagateTo (finalX, magneticField)) {
506490 return -4 ; // failed to propagate
@@ -511,17 +495,15 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
511495 return nIntercepts;
512496
513497 // generate efficiency
514- if (applyEffCorrection) {
515- dNdEtaCent = nch;
516- float eff = 1 .;
517- for (int i = 0 ; i < kMaxNumberOfDetectors ; i++) {
518- float iGoodHit = goodHitProbability[i];
519- if (iGoodHit <= 0 )
520- continue ;
521-
522- eff *= iGoodHit;
523- }
498+ float eff = 1 .;
499+ for (int i = 0 ; i < kMaxNumberOfDetectors ; i++) {
500+ float iGoodHit = goodHitProbability[i];
501+ if (iGoodHit <= 0 )
502+ continue ;
524503
504+ eff *= iGoodHit;
505+ }
506+ if (mApplyEffCorrection ) {
525507 if (gRandom ->Uniform () > eff)
526508 return -8 ;
527509 }
@@ -530,11 +512,11 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
530512 outputTrack.checkCovariance ();
531513
532514 // Use covariance matrix based smearing
533- std::array<double , 15 > covMat = {0 .};
534- for (int ii = 0 ; ii < 15 ; ii++)
515+ std::array<float , o2::track:: kCovMatSize > covMat = {0 .};
516+ for (int ii = 0 ; ii < o2::track:: kCovMatSize ; ii++)
535517 covMat[ii] = outputTrack.getCov ()[ii];
536518 TMatrixDSym m (5 );
537- double fcovm[5 ][5 ];
519+ float fcovm[5 ][5 ];
538520
539521 for (int ii = 0 , k = 0 ; ii < 5 ; ++ii) {
540522 for (int j = 0 ; j < ii + 1 ; ++j, ++k) {
@@ -544,7 +526,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
544526 }
545527
546528 // evaluate ruben's conditional, regularise
547- bool makePositiveDefinite = (covMatFactor > -1e-5 ); // apply fix
529+ const bool makePositiveDefinite = (covMatFactor > -1e-5 ); // apply fix
548530 bool rubenConditional = false ;
549531 for (int ii = 0 ; ii < 5 ; ii++) {
550532 for (int jj = 0 ; jj < 5 ; jj++) {
@@ -571,7 +553,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
571553 }
572554
573555 if (negEigVal && rubenConditional && makePositiveDefinite) {
574- if (verboseLevel > 0 ) {
556+ if (mVerboseLevel > 0 ) {
575557 LOG (info) << " WARNING: this diagonalization (at pt = " << inputTrack.getPt () << " ) has negative eigenvalues despite Ruben's fix! Please be careful!" ;
576558 LOG (info) << " Printing info:" ;
577559 LOG (info) << " Kalman updates: " << nIntercepts;
@@ -585,9 +567,9 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
585567 covMatOK++;
586568
587569 // transform parameter vector and smear
588- double params_[5 ];
570+ float params_[5 ];
589571 for (int ii = 0 ; ii < 5 ; ++ii) {
590- double val = 0 .;
572+ float val = 0 .;
591573 for (int j = 0 ; j < 5 ; ++j)
592574 val += eigVec[j][ii] * outputTrack.getParam (j);
593575 // smear parameters according to eigenvalues
@@ -598,7 +580,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa
598580 eigVec.Invert ();
599581 // transform back params vector
600582 for (int ii = 0 ; ii < 5 ; ++ii) {
601- double val = 0 .;
583+ float val = 0 .;
602584 for (int j = 0 ; j < 5 ; ++j)
603585 val += eigVec[j][ii] * params_[j];
604586 outputTrack.setParam (val, ii);
0 commit comments