@@ -78,10 +78,11 @@ enum trackQuality {
7878 kNCrossedRowsCut = 5 ,
7979 kTpcChi2Cut = 6 ,
8080 kItsChi2Cut = 7 ,
81- kNtrackQuality = 8
81+ kDcaCuts = 8 ,
82+ kNtrackQuality = 9
8283};
8384
84- std::array<std::string, trackQuality::kNtrackQuality > trackQualityLabels{" All" , " #eta cut" , " #it{p}_{TPC}^{min} cut" , " #it{N}_{cls}^{ITS} cut" , " #it{N}_{cls}^{TPC} cut" , " Crossed rows cut" , " #chi^{2}_{TPC} cut" , " #chi^{2}_{ITS} cut" };
85+ std::array<std::string, trackQuality::kNtrackQuality > trackQualityLabels{" All" , " #eta cut" , " #it{p}_{TPC}^{min} cut" , " #it{N}_{cls}^{ITS} cut" , " #it{N}_{cls}^{TPC} cut" , " Crossed rows cut" , " #chi^{2}_{TPC} cut" , " #chi^{2}_{ITS} cut" , " DCA cuts " };
8586
8687} // namespace
8788
@@ -125,6 +126,8 @@ struct nucleiQC {
125126 Configurable<float > cfgCutNclusCrossedRowsTPC{" cfgCutNclusCrossedRowsTPC" , 70 , " Minimum number of TPC clusters crossed rows" };
126127 Configurable<float > cfgCutChi2PerClusterTPC{" cfgCutChi2PerClusterTPC" , 4 .f , " Maximum chi2 per TPC cluster" };
127128 Configurable<float > cfgCutChi2PerClusterITS{" cfgCutChi2PerClusterITS" , 36 .f , " Maximum chi2 per ITS cluster" };
129+ Configurable<float > cfgCutDCAxy{" cfgCutDCAxy" , 10 .f , " Maximum DCA in the transverse plane" };
130+ Configurable<float > cfgCutDCAz{" cfgCutDCAz" , 10 .f , " Maximum DCA in the longitudinal direction" };
128131
129132 Configurable<LabeledArray<double >> cfgNsigmaTPC{" cfgNsigmaTPC" , {nuclei::nSigmaTPCdefault[0 ], nuclei::Species::kNspecies , 2 , nuclei::names, nuclei::nSigmaConfigName}, " TPC nsigma selection for light nuclei" };
130133 Configurable<LabeledArray<double >> cfgNsigmaTOF{" cfgNsigmaTOF" , {nuclei::nSigmaTOFdefault[0 ], nuclei::Species::kNspecies , 2 , nuclei::names, nuclei::nSigmaConfigName}, " TPC nsigma selection for light nuclei" };
@@ -142,6 +145,7 @@ struct nucleiQC {
142145 {" hEventSelections" , " Event selections; Selection step; Counts" , {HistType::kTH1D , {{nuclei::evSel::kNevSels + 1 , -0 .5f , static_cast <float >(nuclei::evSel::kNevSels ) + 0 .5f }}}},
143146 {" hVtxZBefore" , " Vertex distribution in Z before selections;Z (cm)" , {HistType::kTH1F , {{400 , -20.0 , 20.0 }}}},
144147 {" hVtxZ" , " Vertex distribution in Z;Z (cm)" , {HistType::kTH1F , {{400 , -20.0 , 20.0 }}}},
148+ {" hCentrality" , " Centrality distribution;Centrality (%)" , {HistType::kTH1F , {{100 , 0.0 , 100.0 }}}},
145149 {" hFailCentrality" , " 0: all the times the centrality filling function is called - 1: each time it fails ; Bool" , {HistType::kTH1F , {{2 , -0.5 , 1.50 }}}},
146150 {" hTrackTunedTracks" , " " , {HistType::kTH1F , {{1 , 0.5 , 1.5 }}}},
147151 },
@@ -252,8 +256,8 @@ struct nucleiQC {
252256 LOGF (info, " Retrieved GRP for timestamp %ull (%i) with magnetic field of %1.2f kZG" , timestamp, mRunNumber , mBz );
253257 }
254258
255- template <int iSpecies, typename Ttrack>
256- bool trackSelection (const Ttrack& track)
259+ template <int iSpecies, typename Ttrack, typename Tcollision >
260+ bool trackSelection (const Ttrack& track, const Tcollision& collision )
257261 {
258262 mHistograms .fill (HIST (nuclei::cNames[iSpecies]) + HIST (" /hTrackQuality" ), track.sign () * track.pt (), trackQuality::kNoCuts );
259263
@@ -285,6 +289,16 @@ struct nucleiQC {
285289 return false ;
286290 mHistograms .fill (HIST (nuclei::cNames[iSpecies]) + HIST (" /hTrackQuality" ), track.sign () * track.pt (), trackQuality::kItsChi2Cut );
287291
292+ const o2::math_utils::Point3D<float > collisionVertex{collision.posX (), collision.posY (), collision.posZ ()};
293+ mDcaInfoCov .set (999 , 999 , 999 , 999 , 999 );
294+ setTrackParCov (track, mTrackParCov );
295+ mTrackParCov .setPID (track.pidForTracking ());
296+ std::array<float , 2 > dcaInfo;
297+ o2::base::Propagator::Instance ()->propagateToDCA (collisionVertex, mTrackParCov , mBz , 2 .f , static_cast <o2::base::Propagator::MatCorrType>(cfgMaterialCorrection.value ), &dcaInfo);
298+ if (std::abs (dcaInfo[0 ]) > cfgCutDCAxy || std::abs (dcaInfo[1 ]) > cfgCutDCAz)
299+ return false ;
300+ mHistograms .fill (HIST (nuclei::cNames[iSpecies]) + HIST (" /hTrackQuality" ), track.sign () * track.pt (), trackQuality::kDcaCuts );
301+
288302 return true ;
289303 }
290304
@@ -293,7 +307,7 @@ struct nucleiQC {
293307 {
294308 constexpr int kIndex = iSpecies;
295309 if (!nuclei::checkSpeciesValidity (kIndex ))
296- std::runtime_error (" species contains invalid nucleus kIndex" );
310+ throw std::runtime_error (" species contains invalid nucleus kIndex" );
297311
298312 float centrality = nuclei::getCentrality (collision, cfgCentralityEstimator);
299313 float nsigmaTPC = mPidManagers [kIndex ].getNSigmaTPC (track);
@@ -329,7 +343,7 @@ struct nucleiQC {
329343 }
330344
331345 if (particle.isPhysicalPrimary ()) {
332- candidate.flags |= nuclei::Flags:: kIsPhysicalPrimary ;
346+ candidate.flags |= nuclei::QcFlags:: kQcIsPhysicalPrimary ;
333347
334348 // /< heavy flavour mother
335349 /* if (particle.has_mothers()) {
@@ -344,52 +358,33 @@ struct nucleiQC {
344358
345359 } else if (particle.getProcess () == TMCProcess::kPDecay ) {
346360 // /< assuming that strong decays are included in the previous step
347- candidate.flags |= nuclei::Flags:: kIsSecondaryFromWeakDecay ;
361+ candidate.flags |= nuclei::QcFlags:: kQcIsSecondaryFromWeakDecay ;
348362 } else {
349- candidate.flags |= nuclei::Flags:: kIsSecondaryFromMaterial ;
363+ candidate.flags |= nuclei::QcFlags:: kQcIsSecondaryFromMaterial ;
350364 }
351365 }
352366
353- void fillSpeciesFlags (const int iSpecies, nuclei::SlimCandidate& candidate)
367+ template <typename Tparticle>
368+ void fillCollisionFlag (const Tparticle& particle, nuclei::SlimCandidate& candidate, const std::vector<bool >& reconstructedCollision)
354369 {
355-
356- switch (iSpecies) {
357- case nuclei::Species::kPr :
358- candidate.flags |= nuclei::Flags::kProton ;
359- break ;
360- case nuclei::Species::kDe :
361- candidate.flags |= nuclei::Flags::kDeuteron ;
362- break ;
363- case nuclei::Species::kTr :
364- candidate.flags |= nuclei::Flags::kTriton ;
365- break ;
366- case nuclei::Species::kHe :
367- candidate.flags |= nuclei::Flags::kHe3 ;
368- break ;
369- case nuclei::Species::kAl :
370- candidate.flags |= nuclei::Flags::kHe4 ;
371- break ;
372- default :
373- candidate.flags |= 0 ;
374- break ;
370+ if (reconstructedCollision[particle.mcCollisionId ()]) {
371+ candidate.flags |= nuclei::QcFlags::kQcHasReconstructedCollision ;
375372 }
376373 }
377374
378375 template <typename Tcollision, typename Ttrack>
379- void fillNucleusFlagsPdgs (const int iSpecies, const Tcollision& collision, const Ttrack& track, nuclei::SlimCandidate& candidate)
376+ void fillNucleusFlagsPdgs (const Tcollision& collision, const Ttrack& track, nuclei::SlimCandidate& candidate)
380377 {
381378 candidate.flags = static_cast <uint16_t >((track.pidForTracking () & 0xF ) << 12 );
382379
383- fillSpeciesFlags (iSpecies, candidate);
384-
385380 if (track.hasTOF ())
386- candidate.flags |= nuclei::Flags:: kHasTOF ;
381+ candidate.flags |= nuclei::QcFlags:: kQcHasTOF ;
387382
388383 if (track.hasTRD ())
389- candidate.flags |= nuclei::Flags:: kHasTRD ;
384+ candidate.flags |= nuclei::QcFlags:: kQcHasTRD ;
390385
391386 if (!collision.selection_bit (o2::aod::evsel::kNoITSROFrameBorder ))
392- candidate.flags |= nuclei::Flags:: kITSrof ;
387+ candidate.flags |= nuclei::QcFlags:: kQcITSrof ;
393388 }
394389
395390 template <typename Tparticle>
@@ -405,8 +400,6 @@ struct nucleiQC {
405400 void fillDcaInformation (const int iSpecies, const Tcollision& collision, const Ttrack& track, nuclei::SlimCandidate& candidate, const aod::McParticles::iterator& particle)
406401 {
407402
408- const o2::math_utils::Point3D<float > collisionVertex{collision.posX (), collision.posY (), collision.posZ ()};
409-
410403 mDcaInfoCov .set (999 , 999 , 999 , 999 , 999 );
411404 setTrackParCov (track, mTrackParCov );
412405 mTrackParCov .setPID (track.pidForTracking ());
@@ -432,7 +425,7 @@ struct nucleiQC {
432425 nuclei::SlimCandidate fillCandidate (const int iSpecies, Tcollision const & collision, Ttrack const & track)
433426 {
434427 if (!nuclei::checkSpeciesValidity (iSpecies))
435- std::runtime_error (" species contains invalid nucleus index" );
428+ throw std::runtime_error (" species contains invalid nucleus index" );
436429
437430 nuclei::SlimCandidate candidate = {.pt = track.pt () * track.sign (),
438431 .eta = track.eta (),
@@ -455,7 +448,7 @@ struct nucleiQC {
455448 .nsigmaTpc = mPidManagers [iSpecies].getNSigmaTPC (track),
456449 .nsigmaTof = mPidManagers [iSpecies].getNSigmaTOF (track)};
457450
458- fillNucleusFlagsPdgs (iSpecies, collision, track, candidate);
451+ fillNucleusFlagsPdgs (collision, track, candidate);
459452
460453 aod::McParticles::iterator particle;
461454
@@ -497,7 +490,7 @@ struct nucleiQC {
497490 {
498491 constexpr int kIndex = iSpecies;
499492 if (!nuclei::checkSpeciesValidity (kIndex ))
500- std::runtime_error (" species contains invalid nucleus kIndex" );
493+ throw std::runtime_error (" species contains invalid nucleus kIndex" );
501494
502495 if (isGenerated) {
503496 const float ptGenerated = (kIndex == nuclei::Species::kPr || kIndex == nuclei::Species::kDe || kIndex == nuclei::Species::kTr ) ? candidate.ptGenerated : candidate.ptGenerated / 2 .f ;
@@ -517,11 +510,12 @@ struct nucleiQC {
517510 }
518511 }
519512
520- void processMc (const Collisions& collisions, const TrackCandidatesMC& tracks, const aod::BCsWithTimestamps&, const aod::McParticles& mcParticles)
513+ void processMc (const Collisions& collisions, const TrackCandidatesMC& tracks, const aod::BCsWithTimestamps&, const aod::McParticles& mcParticles, const aod::McCollisions& mcCollisions )
521514 {
522515 gRandom ->SetSeed (67 );
523516 mNucleiCandidates .clear ();
524517 std::vector<bool > reconstructedMcParticles (mcParticles.size (), false );
518+ std::vector<bool > reconstructedCollisions (mcCollisions.size (), false );
525519
526520 for (const auto & collision : collisions) {
527521
@@ -530,6 +524,8 @@ struct nucleiQC {
530524
531525 if (!nuclei::eventSelection (collision, mHistograms , cfgEventSelections, cfgCutVertex))
532526 continue ;
527+ mHistograms .fill (HIST (" hCentrality" ), nuclei::getCentrality (collision, cfgCentralityEstimator, mHistFailCentrality ));
528+ reconstructedCollisions[collision.mcCollisionId ()] = true ;
533529
534530 bool anyTrackTuner = false ;
535531 for (int iSpecies = 0 ; iSpecies < static_cast <int >(nuclei::Species::kNspecies ); iSpecies++) {
@@ -578,10 +574,8 @@ struct nucleiQC {
578574 if (cfgFillOnlyPhysicalPrimaries && !particle.isPhysicalPrimary ())
579575 return ;
580576
581- LOG (info) << " track passed physical primary cut" ;
582-
583577 mHistograms .fill (HIST (nuclei::cNames[kSpeciesCt ]) + HIST (" /hTrackSelections" ), nuclei::trackSelection::kNoCuts );
584- if (!trackSelection<kSpeciesRt >(track))
578+ if (!trackSelection<kSpeciesRt >(track, collision ))
585579 return ;
586580 mHistograms .fill (HIST (nuclei::cNames[kSpeciesCt ]) + HIST (" /hTrackSelections" ), nuclei::trackSelection::kTrackCuts );
587581
@@ -591,6 +585,7 @@ struct nucleiQC {
591585
592586 nuclei::SlimCandidate candidate;
593587 candidate = fillCandidate</* isMc*/ true >(kSpeciesCt , collision, track);
588+ fillCollisionFlag (particle, candidate, reconstructedCollisions);
594589
595590 mNucleiCandidates .emplace_back (candidate);
596591 reconstructedMcParticles[particle.globalIndex ()] = true ;
@@ -627,7 +622,7 @@ struct nucleiQC {
627622 nuclei::SlimCandidate candidate;
628623 // candidate.centrality = nuclei::getCentrality(collision, cfgCentralityEstimator, mHistFailCentrality);
629624 candidate.centrality = -1 .f ; // centrality is not well defined for non-reconstructed particles, set to -1 for now
630- fillSpeciesFlags (iSpecies , candidate);
625+ fillCollisionFlag (particle , candidate, reconstructedCollisions );
631626 fillNucleusFlagsPdgsMc (particle, candidate);
632627 fillNucleusGeneratedVariables (particle, candidate);
633628
0 commit comments