@@ -119,8 +119,8 @@ struct UpcRhoAnalysis {
119119 Configurable<bool > saveKaons{" saveKaons" , false , " save kaon tracks into derived tables" };
120120
121121 float pcEtaCut = 0.9 ; // physics coordination recommendation
122+ Configurable<int > numPions{" numPions" , 2 , " required number of pions in the event" };
122123 Configurable<bool > requireTof{" requireTof" , false , " require TOF signal" };
123- // Configurable<int> selectedMcGeneratorId{"selectedMcGeneratorId", 0, "flag for selected MC process ID"};
124124
125125 Configurable<float > collisionsPosZMaxCut{" collisionsPosZMaxCut" , 10.0 , " max Z position cut on collisions" };
126126 Configurable<int > collisionsNumContribsMaxCut{" collisionsNumContribsMaxCut" , 5 , " max number of contributors cut on collisions" };
@@ -131,7 +131,7 @@ struct UpcRhoAnalysis {
131131 Configurable<float > tracksTpcNSigmaElCut{" tracksTpcNSigmaElCut" , 3.0 , " TPC nSigma electron cut" };
132132 Configurable<float > tracksTpcNSigmaKaCut{" tracksTpcNSigmaKaCut" , 3.0 , " TPC nSigma kaon cut" };
133133 Configurable<float > tracksDcaMaxCut{" tracksDcaMaxCut" , 1.0 , " max DCA cut on tracks" };
134- Configurable<int > tracksMinItsNClsCut{" tracksMinItsNClsCut" , 6 , " min ITS clusters cut" };
134+ Configurable<int > tracksMinItsNClsCut{" tracksMinItsNClsCut" , 4 , " min ITS clusters cut" };
135135 Configurable<float > tracksMaxItsChi2NClCut{" tracksMaxItsChi2NClCut" , 3.0 , " max ITS chi2/Ncls cut" };
136136 Configurable<int > tracksMinTpcNClsCut{" tracksMinTpcNClsCut" , 120 , " min TPC clusters cut" };
137137 Configurable<int > tracksMinTpcNClsCrossedRowsCut{" tracksMinTpcNClsCrossedRowsCut" , 140 , " min TPC crossed rows cut" };
@@ -211,7 +211,7 @@ struct UpcRhoAnalysis {
211211 rQC.add (" QC/tracks/selected/hTpcNSigmaEl2D" , " ;TPC n#sigma(e_{leading});TPC n#sigma(e_{subleading});counts" , kTH2D , {{400 , -10.0 , 30.0 }, {400 , -10.0 , 30.0 }});
212212 rQC.add (" QC/tracks/selected/hTpcNSigmaKa2D" , " ;TPC n#sigma(K_{leading});TPC n#sigma(K_{subleading});counts" , kTH2D , {{400 , -10.0 , 30.0 }, {400 , -10.0 , 30.0 }});
213213 // selection counter
214- std::vector<std::string> selectionCounterLabels = {" all tracks" , " PV contributor" , " ITS hit" , " ITS N_{clusters}" , " ITS #chi^{2}/N_{clusters}" , " TPC hit" , " TPC N_{clusters} found" , " TPC #chi^{2}/N_{clusters}" , " TPC crossed rows" ,
214+ std::vector<std::string> selectionCounterLabels = {" all tracks" , " PV contributor" , " ITS hit" , " ITS N_{clusters}" , " hit in innermost ITS layer " , " ITS #chi^{2}/N_{clusters}" , " TPC hit" , " TPC N_{clusters} found" , " TPC #chi^{2}/N_{clusters}" , " TPC crossed rows" ,
215215 " TPC crossed rows/N_{clusters}" ,
216216 " TOF requirement" ,
217217 " p_{T}" , " DCA" , " #eta" , " exactly 2 tracks" };
@@ -355,6 +355,23 @@ struct UpcRhoAnalysis {
355355 }
356356 }
357357
358+ bool cutItsLayers (uint8_t itsClusterMap) const
359+ {
360+ std::vector<std::pair<int8_t , std::array<uint8_t , 3 >>> requiredITSHits{};
361+ requiredITSHits.push_back (std::make_pair (1 , std::array<uint8_t , 3 >{0 , 1 , 2 })); // at least one hit in the innermost layer
362+ constexpr uint8_t kBit = 1 ;
363+ for (const auto & itsRequirement : requiredITSHits) {
364+ auto hits = std::count_if (itsRequirement.second .begin (), itsRequirement.second .end (), [&](auto && requiredLayer) { return itsClusterMap & (kBit << requiredLayer); });
365+
366+ if ((itsRequirement.first == -1 ) && (hits > 0 )) {
367+ return false ; // no hits were required in specified layers
368+ } else if (hits < itsRequirement.first ) {
369+ return false ; // not enough hits found in specified layers
370+ }
371+ }
372+ return true ;
373+ }
374+
358375 template <typename C>
359376 bool collisionPassesCuts (const C& collision) // collision cuts
360377 {
@@ -383,55 +400,60 @@ struct UpcRhoAnalysis {
383400 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 3 );
384401 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 3 , collision.runNumber ());
385402
386- if (track.itsChi2NCl () > tracksMaxItsChi2NClCut )
403+ if (! cutItsLayers ( track.itsClusterMap ()) )
387404 return false ;
388405 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 4 );
389406 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 4 , collision.runNumber ());
390407
391- if (! track.hasTPC () )
408+ if (track.itsChi2NCl () > tracksMaxItsChi2NClCut )
392409 return false ;
393410 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 5 );
394411 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 5 , collision.runNumber ());
395412
396- if (( track.tpcNClsFindable () - track. tpcNClsFindableMinusFound ()) < tracksMinTpcNClsCut )
413+ if (! track.hasTPC () )
397414 return false ;
398415 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 6 );
399416 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 6 , collision.runNumber ());
400417
401- if (track.tpcChi2NCl () > tracksMaxTpcChi2NClCut || track.tpcChi2NCl () < tracksMinTpcChi2NClCut )
418+ if (( track.tpcNClsFindable () - track.tpcNClsFindableMinusFound ()) < tracksMinTpcNClsCut )
402419 return false ;
403420 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 7 );
404421 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 7 , collision.runNumber ());
405422
406- if (track.tpcNClsCrossedRows () < tracksMinTpcNClsCrossedRowsCut )
423+ if (track.tpcChi2NCl () > tracksMaxTpcChi2NClCut || track. tpcChi2NCl () < tracksMinTpcChi2NClCut )
407424 return false ;
408425 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 8 );
409426 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 8 , collision.runNumber ());
410427
411- if (( static_cast < double >( track.tpcNClsCrossedRows ()) / static_cast < double >(track. tpcNClsFindable ())) < tracksMinTpcNClsCrossedOverFindableCut )
428+ if (track.tpcNClsCrossedRows () < tracksMinTpcNClsCrossedRowsCut )
412429 return false ;
413430 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 9 );
414431 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 9 , collision.runNumber ());
415432
416- if (requireTof && ! track.hasTOF () )
433+ if (( static_cast < double >(track. tpcNClsCrossedRows ()) / static_cast < double >( track.tpcNClsFindable ())) < tracksMinTpcNClsCrossedOverFindableCut )
417434 return false ;
418435 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 10 );
419436 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 10 , collision.runNumber ());
420437
421- if (track.pt () < tracksMinPtCut )
438+ if (requireTof && ! track.hasTOF () )
422439 return false ;
423440 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 11 );
424441 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 11 , collision.runNumber ());
425442
426- if (std::abs ( track.dcaZ ()) > tracksDcaMaxCut || std::abs (track. dcaXY ()) > ( 0.0105 + 0.0350 / std::pow (track. pt (), 1.01 )) )
443+ if (track.pt () < tracksMinPtCut )
427444 return false ;
428445 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 12 );
429446 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 12 , collision.runNumber ());
430447
431- if (std::abs (eta ( track.px (), track.py (), track.pz ())) > pcEtaCut )
448+ if (std::abs (track.dcaZ ()) > tracksDcaMaxCut || std::abs ( track.dcaXY ()) > ( 0.0105 + 0.0350 / std::pow ( track.pt (), 1.01 )) )
432449 return false ;
433450 rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 13 );
434451 rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 13 , collision.runNumber ());
452+
453+ if (std::abs (eta (track.px (), track.py (), track.pz ())) > pcEtaCut)
454+ return false ;
455+ rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 14 );
456+ rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 14 , collision.runNumber ());
435457 // if all selections passed
436458 return true ;
437459 }
@@ -576,11 +598,11 @@ struct UpcRhoAnalysis {
576598 }
577599 rQC.fill (HIST (" QC/tracks/selected/hRemainingTracks" ), cutTracks.size ());
578600
579- if (cutTracks.size () != 2 ) // further consider only two pion systems
601+ if (static_cast < int >( cutTracks.size ()) != numPions ) // further consider only two pion systems
580602 return ;
581603 for (int i = 0 ; i < static_cast <int >(cutTracks.size ()); i++) {
582- rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 14 );
583- rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 14 , collision.runNumber ());
604+ rQC.fill (HIST (" QC/tracks/hSelectionCounter" ), 15 );
605+ rQC.fill (HIST (" QC/tracks/hSelectionCounterPerRun" ), 15 , collision.runNumber ());
584606 }
585607 rQC.fill (HIST (" QC/tracks/selected/hTpcNSigmaPi2D" ), cutTracks[0 ].tpcNSigmaPi (), cutTracks[1 ].tpcNSigmaPi ());
586608 rQC.fill (HIST (" QC/tracks/selected/hTpcNSigmaEl2D" ), cutTracks[0 ].tpcNSigmaEl (), cutTracks[1 ].tpcNSigmaEl ());
@@ -714,8 +736,6 @@ struct UpcRhoAnalysis {
714736 template <typename C, typename T>
715737 void processMC (C const & mcCollision, T const & mcParticles)
716738 {
717- // if (mcCollision.getGeneratorId() != selectedMcGeneratorId)
718- // return;
719739 rMC.fill (HIST (" MC/collisions/hPosXY" ), mcCollision.posX (), mcCollision.posY ());
720740 rMC.fill (HIST (" MC/collisions/hPosZ" ), mcCollision.posZ ());
721741
@@ -738,7 +758,7 @@ struct UpcRhoAnalysis {
738758 }
739759 rMC.fill (HIST (" MC/collisions/hNPions" ), cutMcParticles.size ());
740760
741- if (cutMcParticles.size () != 2 )
761+ if (static_cast < int >( cutMcParticles.size ()) != numPions )
742762 return ;
743763 if (mcParticlesLVs.size () != cutMcParticles.size ())
744764 return ;
0 commit comments