@@ -48,6 +48,12 @@ using namespace std;
4848#define ID_BIT_EL 3
4949#define ID_BIT_DE 4
5050
51+ #define MC_BIT_PI 0 // MC particle identification bits
52+ #define MC_BIT_KA 1
53+ #define MC_BIT_PR 2
54+ #define MC_BIT_EL 3
55+ #define MC_BIT_DE 4
56+
5157#define BITSET (mask, ithBit ) ((mask) |= (1 << (ithBit))) // avoid name bitset as std::bitset is already there
5258#define BITCHECK (mask, ithBit ) ((mask) & (1 << (ithBit))) // bit check will return int value, not bool, use BITCHECK != 0 in Analysi
5359
@@ -108,6 +114,7 @@ struct NchCumulantsId {
108114
109115 Configurable<bool > checkCollPosZMc{" checkCollPosZMc" , false , " checkCollPosZMc" };
110116 Configurable<bool > flagUnusedVariableError{" flagUnusedVariableError" , false , " flagUnusedVariableError" };
117+ Configurable<bool > cfgDoRejectionForId{" cfgDoRejectionForId" , false , " Apply rejection cut before PID selection (selTrackForId)" };
111118
112119 Configurable<bool > cfgEvSel01doNoSameBunchPileup{" cfgEvSel01doNoSameBunchPileup" , true , " apply kNoSameBunchPileup" };
113120 Configurable<bool > cfgEvSel02doIsGoodZvtxFT0vsPV{" cfgEvSel02doIsGoodZvtxFT0vsPV" , true , " apply kIsGoodZvtxFT0vsPV" };
@@ -150,6 +157,12 @@ struct NchCumulantsId {
150157 Configurable<float > cfgIdPr08NSigmaTOFHighP{" cfgIdPr08NSigmaTOFHighP" , 2.0 , " cfgIdPr08NSigmaTOFHighP" };
151158 Configurable<float > cfgIdPr09NSigmaRadHighP{" cfgIdPr09NSigmaRadHighP" , 4.0 , " cfgIdPr09NSigmaRadHighP" };
152159
160+ Configurable<float > cfgIdElRejLowNSigma{" cfgIdElRejLowNSigma" , -3.0 , " cfgIdElRejLowNSigma" };
161+ Configurable<float > cfgIdElRejHighNSigma{" cfgIdElRejHighNSigma" , 5.0 , " cfgIdElRejHighNSigma" };
162+ Configurable<float > cfgIdPiRejNSigma{" cfgIdPiRejNSigma" , 3.0 , " cfgIdPiRejNSigma" };
163+ Configurable<float > cfgIdKaRejNSigma{" cfgIdKaRejNSigma" , 3.0 , " cfgIdKaRejNSigma" };
164+ Configurable<float > cfgIdPrRejNSigma{" cfgIdPrRejNSigma" , 3.0 , " cfgIdPrRejNSigma" };
165+
153166 struct : ConfigurableGroup {
154167 Configurable<float > cfgVetoId01PiTPC{" cfgVetoId01PiTPC" , 3.0 , " cfgVetoId01PiTPC" };
155168 Configurable<float > cfgVetoId02PiTOF{" cfgVetoId02PiTOF" , 3.0 , " cfgVetoId02PiTOF" };
@@ -244,8 +257,13 @@ struct NchCumulantsId {
244257 const AxisSpec axisPiCh (101 , -1 , 100 , " Pion_Positive" );
245258 const AxisSpec axisAPiCh (101 , -1 , 100 , " Pion_Negative" );
246259
260+ const AxisSpec axisIdTag = {32 , -0 .5f , 31 .5f , " idTag" };
261+ const AxisSpec axisMcTag = {32 , -0 .5f , 31 .5f , " mcTag" };
262+
247263 HistogramConfigSpec qnHist1 ({HistType::kTHnSparseD , {axisNch, axisPosCh, axisNegCh, axisPrCh, axisAPrCh, axisKaCh, axisAKaCh, axisNt, axisCent}});
248264 HistogramConfigSpec qnHist2 ({HistType::kTHnSparseD , {axisNch, axisPosCh, axisNegCh, axisPiCh, axisAPiCh, axisKaCh, axisAKaCh, axisNt, axisCent}});
265+ HistogramConfigSpec histTPCPIDSparse ({HistType::kTHnSparseD , {axisP, axisTPCNSigma, axisIdTag, axisMcTag}});
266+ HistogramConfigSpec histTOFPIDSparse ({HistType::kTHnSparseD , {axisP, axisTOFNSigma, axisIdTag, axisMcTag}});
249267
250268 HistogramConfigSpec histPPt ({HistType::kTH2F , {axisP, axisPt}});
251269 HistogramConfigSpec histPTpcInnerParam ({HistType::kTH2F , {axisP, axisTPCInnerParam}});
@@ -265,6 +283,17 @@ struct NchCumulantsId {
265283
266284 HistogramConfigSpec histPtMc ({HistType::kTH1F , {axisPt}});
267285
286+ // Register histograms for PID validation
287+ // Register TPC spares per species
288+ hist.add (" PIDValidation/tpcSparse_Pi" , " p vs tpcNSigmaPi vs idTag vs mcTag (Pion)" , histTPCPIDSparse);
289+ hist.add (" PIDValidation/tpcSparse_Ka" , " p vs tpcNSigmaKa vs idTag vs mcTag (Kaon)" , histTPCPIDSparse);
290+ hist.add (" PIDValidation/tpcSparse_Pr" , " p vs tpcNSigmaPr vs idTag vs mcTag (Proton)" , histTPCPIDSparse);
291+
292+ // Register TOF spares per species
293+ hist.add (" PIDValidation/tofSparse_Pi" , " p vs tofNSigmaPi vs idTag vs mcTag (Pion)" , histTOFPIDSparse);
294+ hist.add (" PIDValidation/tofSparse_Ka" , " p vs tofNSigmaKa vs idTag vs mcTag (Kaon)" , histTOFPIDSparse);
295+ hist.add (" PIDValidation/tofSparse_Pr" , " p vs tofNSigmaPr vs idTag vs mcTag (Proton)" , histTOFPIDSparse);
296+
268297 // QA check histos
269298
270299 hist.add (" QA/events/preSel/h_VtxZ" , " V_{Z}" , kTH1D , {axisVtxZ});
@@ -762,8 +791,44 @@ struct NchCumulantsId {
762791 }
763792 }
764793
794+ template <typename T>
795+ int getMCTag (const T& track)
796+ {
797+ int mcTag = 0 ;
798+ if (!track.has_mcParticle ())
799+ return mcTag;
800+ auto mcPart = track.mcParticle ();
801+ int pdgCode = std::abs (mcPart.pdgCode ());
802+
803+ if (pdgCode == kPiPlus || pdgCode == kPiMinus )
804+ BITSET (mcTag, MC_BIT_PI);
805+ else if (pdgCode == kKPlus || pdgCode == kKMinus )
806+ BITSET (mcTag, MC_BIT_KA);
807+ else if (pdgCode == kProton || pdgCode == kProtonBar )
808+ BITSET (mcTag, MC_BIT_PR);
809+ else if (pdgCode == kElectron || pdgCode == kPositron )
810+ BITSET (mcTag, MC_BIT_EL);
811+ else if (pdgCode == kDeuteron || pdgCode == -kDeuteron )
812+ BITSET (mcTag, MC_BIT_DE);
813+
814+ return mcTag;
815+ }
765816 //
766817 // ______________________________Identification Functions________________________________________________________________
818+ // Victor slection cuts for electron and other rejections
819+ template <typename T>
820+ bool selTrackForId (const T& track)
821+ {
822+ if (cfgIdElRejLowNSigma < track.tpcNSigmaEl () && track.tpcNSigmaEl () < cfgIdElRejHighNSigma &&
823+ std::fabs (track.tpcNSigmaPi ()) > cfgIdPiRejNSigma &&
824+ std::fabs (track.tpcNSigmaKa ()) > cfgIdKaRejNSigma &&
825+ std::fabs (track.tpcNSigmaPr ()) > cfgIdPrRejNSigma) {
826+ return false ;
827+ } else {
828+ return true ;
829+ }
830+ }
831+
767832 // Pion
768833 template <typename T>
769834 bool selPion (const T& track, int & IdMethod)
@@ -1137,6 +1202,11 @@ struct NchCumulantsId {
11371202 nM += hPtEtaForEffCorrection[kCh ][kNeg ]->GetBinContent (ptEtaBin);
11381203 }
11391204
1205+ // Reject electrons first
1206+ if (cfgDoRejectionForId && !selTrackForId (track)) {
1207+ continue ;
1208+ }
1209+
11401210 int idMethod;
11411211 // pion
11421212 if (selPion (track, idMethod)) {
@@ -1235,17 +1305,34 @@ struct NchCumulantsId {
12351305 idMethodKa = kUnidentified ;
12361306 idMethodPr = kUnidentified ;
12371307
1308+ // Get MC tag
1309+ int mcTag = getMCTag (track);
1310+
1311+ // Reject electrons first
1312+ if (cfgDoRejectionForId && !selTrackForId (track)) {
1313+ continue ;
1314+ }
1315+
12381316 if (selPion (track, idMethodPi)) {
12391317 trackIsPion = true ;
12401318 BITSET (trackIdTag, ID_BIT_PI);
1319+ hist.fill (HIST (" PIDValidation/tpcSparse_Pi" ), track.p (), track.tpcNSigmaPi (), trackIdTag, mcTag);
1320+ if (track.hasTOF ())
1321+ hist.fill (HIST (" PIDValidation/tofSparse_Pi" ), track.p (), track.tofNSigmaPi (), trackIdTag, mcTag);
12411322 }
12421323 if (selKaon (track, idMethodKa)) {
12431324 trackIsKaon = true ;
12441325 BITSET (trackIdTag, ID_BIT_KA);
1326+ hist.fill (HIST (" PIDValidation/tpcSparse_Ka" ), track.p (), track.tpcNSigmaKa (), trackIdTag, mcTag);
1327+ if (track.hasTOF ())
1328+ hist.fill (HIST (" PIDValidation/tofSparse_Ka" ), track.p (), track.tofNSigmaKa (), trackIdTag, mcTag);
12451329 }
12461330 if (selProton (track, idMethodPr)) {
12471331 trackIsProton = true ;
12481332 BITSET (trackIdTag, ID_BIT_PR);
1333+ hist.fill (HIST (" PIDValidation/tpcSparse_Pr" ), track.p (), track.tpcNSigmaPr (), trackIdTag, mcTag);
1334+ if (track.hasTOF ())
1335+ hist.fill (HIST (" PIDValidation/tofSparse_Pr" ), track.p (), track.tofNSigmaPr (), trackIdTag, mcTag);
12491336 }
12501337
12511338 if constexpr (analysisType == doPurityProcessing) {
@@ -1555,6 +1642,8 @@ struct NchCumulantsId {
15551642 continue ;
15561643 int pdg = mcPart.pdgCode ();
15571644
1645+ int mcTag = getMCTag (track);
1646+
15581647 fillTrackQA<qaTracksPostSel>(track);
15591648
15601649 trackIsPion = false ;
@@ -1565,17 +1654,41 @@ struct NchCumulantsId {
15651654 idMethodKa = kUnidentified ;
15661655 idMethodPr = kUnidentified ;
15671656
1657+ // Reject electrons first
1658+ if (cfgDoRejectionForId && !selTrackForId (track)) {
1659+ continue ;
1660+ }
1661+
1662+ // Fill separate spares for each species if it passes the cut
15681663 if (selPion (track, idMethodPi)) {
15691664 trackIsPion = true ;
15701665 BITSET (trackIdTag, ID_BIT_PI);
1666+ // Fill TPC sparse for pion
1667+ hist.fill (HIST (" PIDValidation/tpcSparse_Pi" ), track.p (), track.tpcNSigmaPi (), trackIdTag, mcTag);
1668+ // Fill TOF sparse for pion if has TOF
1669+ if (track.hasTOF ()) {
1670+ hist.fill (HIST (" PIDValidation/tofSparse_Pi" ), track.p (), track.tofNSigmaPi (), trackIdTag, mcTag);
1671+ }
15711672 }
15721673 if (selKaon (track, idMethodKa)) {
15731674 trackIsKaon = true ;
15741675 BITSET (trackIdTag, ID_BIT_KA);
1676+ // Fill TPC sparse for kaon
1677+ hist.fill (HIST (" PIDValidation/tpcSparse_Ka" ), track.p (), track.tpcNSigmaKa (), trackIdTag, mcTag);
1678+ // Fill TOF sparse for kaon if has TOF
1679+ if (track.hasTOF ()) {
1680+ hist.fill (HIST (" PIDValidation/tofSparse_Ka" ), track.p (), track.tofNSigmaKa (), trackIdTag, mcTag);
1681+ }
15751682 }
15761683 if (selProton (track, idMethodPr)) {
15771684 trackIsProton = true ;
15781685 BITSET (trackIdTag, ID_BIT_PR);
1686+ // Fill TPC sparse for proton
1687+ hist.fill (HIST (" PIDValidation/tpcSparse_Pr" ), track.p (), track.tpcNSigmaPr (), trackIdTag, mcTag);
1688+ // Fill TOF sparse for proton if has TOF
1689+ if (track.hasTOF ()) {
1690+ hist.fill (HIST (" PIDValidation/tofSparse_Pr" ), track.p (), track.tofNSigmaPr (), trackIdTag, mcTag);
1691+ }
15791692 }
15801693
15811694 // bool isKnownCharged = (std::abs(pdg) == kPiPlus ||
@@ -1614,6 +1727,11 @@ struct NchCumulantsId {
16141727 nAPiRec += hPtEtaForEffCorrection[kPi ][kNeg ]->GetBinContent (ptEtaBin);
16151728 fillRecoTrackQA<recoAnalysisDir, kPi , kNeg >(recoAnalysis, track);
16161729 }
1730+ // PID band QA for pions
1731+ if (idMethodPi == kTPCidentified )
1732+ fillIdentificationQA<qaTracksIdfd, kPi , tpcId>(hist, track);
1733+ if (idMethodPi == kTPCTOFidentified )
1734+ fillIdentificationQA<qaTracksIdfd, kPi , tpctofId>(hist, track);
16171735 } else if (trackIsKaon) {
16181736 if (track.sign () > 0 ) {
16191737 nKaRec += hPtEtaForEffCorrection[kKa ][kPos ]->GetBinContent (ptEtaBin);
@@ -1622,6 +1740,11 @@ struct NchCumulantsId {
16221740 nAKaRec += hPtEtaForEffCorrection[kKa ][kNeg ]->GetBinContent (ptEtaBin);
16231741 fillRecoTrackQA<recoAnalysisDir, kKa , kNeg >(recoAnalysis, track);
16241742 }
1743+ // PID band QA for kaons
1744+ if (idMethodKa == kTPCidentified )
1745+ fillIdentificationQA<qaTracksIdfd, kKa , tpcId>(hist, track);
1746+ if (idMethodKa == kTPCTOFidentified )
1747+ fillIdentificationQA<qaTracksIdfd, kKa , tpctofId>(hist, track);
16251748 } else if (trackIsProton) {
16261749 if (track.sign () > 0 ) {
16271750 nPrRec += hPtEtaForEffCorrection[kPr ][kPos ]->GetBinContent (ptEtaBin);
@@ -1630,6 +1753,11 @@ struct NchCumulantsId {
16301753 nAPrRec += hPtEtaForEffCorrection[kPr ][kNeg ]->GetBinContent (ptEtaBin);
16311754 fillRecoTrackQA<recoAnalysisDir, kPr , kNeg >(recoAnalysis, track);
16321755 }
1756+ // PID band QA for protons
1757+ if (idMethodPr == kTPCidentified )
1758+ fillIdentificationQA<qaTracksIdfd, kPr , tpcId>(hist, track);
1759+ if (idMethodPr == kTPCTOFidentified )
1760+ fillIdentificationQA<qaTracksIdfd, kPr , tpctofId>(hist, track);
16331761 }
16341762 // purity check - check pdg aginst sign
16351763 bool purityPion = false ;
0 commit comments