@@ -94,13 +94,15 @@ struct DeltaAnalysis {
9494 Configurable<bool > cfgRequireRecoINELgt0{" cfgRequireRecoINELgt0" , true , " Require reconstructed INEL>0 event class (at least one PV track in |eta|<1)" };
9595 Configurable<bool > cfgUseNoSameBunchPileupCut{" cfgUseNoSameBunchPileupCut" , false , " Apply kNoSameBunchPileup event selection" };
9696 Configurable<bool > cfgUseGoodZvtxFT0vsPVCut{" cfgUseGoodZvtxFT0vsPVCut" , false , " Apply kIsGoodZvtxFT0vsPV event selection" };
97+ Configurable<bool > cfgUseGoodITSLayersAll{" cfgUseGoodITSLayersAll" , false , " Apply kIsGoodITSLayersAll event selection" };
9798 Configurable<bool > applyOccupancyInTimeRangeCut{" applyOccupancyInTimeRangeCut" , false , " Apply occupancy-in-time-range cut" };
9899 Configurable<int > cfgOccupancyMin{" cfgOccupancyMin" , 0 , " Minimum track occupancy in time range" };
99100 Configurable<int > cfgOccupancyMax{" cfgOccupancyMax" , 9999 , " Maximum track occupancy in time range" };
100101 Configurable<int > cfgCentralityEstimator{" cfgCentralityEstimator" , 0 , " Centrality estimator: 0=FT0M 1=FT0A 2=FT0C 3=FV0A 4=NTPV" };
101102 Configurable<float > cfgCentMin{" cfgCentMin" , 0 .f , " Minimum centrality percentile" };
102103 Configurable<float > cfgCentMax{" cfgCentMax" , 100 .f , " Maximum centrality percentile" };
103104 Configurable<bool > cfgUseMCTruthCentrality{" cfgUseMCTruthCentrality" , false , " Use MC truth centrality for generated Delta histograms" };
105+ Configurable<bool > cfgApplyMCTruthINELgt0{" cfgApplyMCTruthINELgt0" , true , " Apply truth-level INEL>0 selection to MC generated events" };
104106 } evSel;
105107
106108 struct : ConfigurableGroup {
@@ -125,7 +127,7 @@ struct DeltaAnalysis {
125127 Configurable<bool > applyTPCChi2NClCut{" applyTPCChi2NClCut" , true , " Enable/disable maximum TPC chi2/NCl cut" };
126128 Configurable<bool > applyITSChi2NClCut{" applyITSChi2NClCut" , true , " Enable/disable maximum ITS chi2/NCl cut" };
127129 Configurable<bool > requirePrimaryTrack{" requirePrimaryTrack" , true , " Require isPrimaryTrack flag" };
128- Configurable<bool > requireGlobalTrackNoDCA{ " requireGlobalTrackNoDCA " , true , " Require isGlobalTrackWoDCA flag " };
130+ Configurable<bool > requireGlobalTrack{ " requireGlobalTrack " , true , " Require global track " };
129131 Configurable<bool > requirePVContributor{" requirePVContributor" , true , " Require PV-contributor flag" };
130132 } trackCuts;
131133
@@ -135,6 +137,10 @@ struct DeltaAnalysis {
135137 Configurable<std::vector<float >> protonMaxDCAxyPerPtBin{" protonMaxDCAxyPerPtBin" , {0 .10f , 0 .08f , 0 .05f , 0 .05f }, " Max |DCAxy| for proton per pT bin [cm]" };
136138 Configurable<std::vector<float >> pionDCAPtBinEdges{" pionDCAPtBinEdges" , {0 .0f , 0 .5f , 1 .0f , 2 .0f , 1000 .f }, " Pion pT bin edges for DCAxy cut [GeV/c]" };
137139 Configurable<std::vector<float >> pionMaxDCAxyPerPtBin{" pionMaxDCAxyPerPtBin" , {0 .20f , 0 .15f , 0 .10f , 0 .08f }, " Max |DCAxy| for pion per pT bin [cm]" };
140+ Configurable<bool > isApplyPtDepDCAxyCut{" isApplyPtDepDCAxyCut" , false , " Use continuous pT-dependent DCAxy cut" };
141+ Configurable<float > dcaXYConst{" dcaXYConst" , 0 .0105f , " Constant term of pT-dependent DCAxy cut [cm]" };
142+ Configurable<float > dcaXYPtCoeff{" dcaXYPtCoeff" , 0 .035f , " pT-dependent coefficient of DCAxy cut [cm]" };
143+ Configurable<float > dcaXYPtExponent{" dcaXYPtExponent" , 1 .1f , " pT exponent of DCAxy cut" };
138144 } dcaCuts;
139145
140146 struct : ConfigurableGroup {
@@ -155,6 +161,7 @@ struct DeltaAnalysis {
155161 Configurable<std::vector<float >> protonTPCNSigmaCutPerBin{" protonTPCNSigmaCutPerBin" , {5 .f , 3 .5f , 2 .5f }, " Maximum TPC nSigma for proton per momentum bin" };
156162 Configurable<std::vector<float >> protonTOFPIDMomentumBins{" protonTOFPIDMomentumBins" , {0 .f , 999 .f }, " Proton TOF PID momentum bin edges [GeV/c]" };
157163 Configurable<std::vector<float >> protonTOFNSigmaCutPerBin{" protonTOFNSigmaCutPerBin" , {3 .0f }, " Maximum TOF nSigma for proton per momentum bin" };
164+ Configurable<float > shiftInNsigmaTOFProton{" shiftInNsigmaTOFProton" , 0 .0f , " Shift applied to proton TOF nSigma" };
158165 } protonPID;
159166
160167 struct : ConfigurableGroup {
@@ -169,6 +176,7 @@ struct DeltaAnalysis {
169176 Configurable<std::vector<float >> pionTPCNSigmaCutPerBin{" pionTPCNSigmaCutPerBin" , {5 .f , 3 .5f , 2 .5f }, " Maximum TPC nSigma for pion per momentum bin" };
170177 Configurable<std::vector<float >> pionTOFPIDMomentumBins{" pionTOFPIDMomentumBins" , {0 .f , 999 .f }, " Pion TOF PID momentum bin edges [GeV/c]" };
171178 Configurable<std::vector<float >> pionTOFNSigmaCutPerBin{" pionTOFNSigmaCutPerBin" , {3 .0f }, " Maximum TOF nSigma for pion per momentum bin" };
179+ Configurable<float > shiftInNsigmaTOFPion{" shiftInNsigmaTOFPion" , 0 .0f , " Shift applied to pion TOF nSigma" };
172180 } pionPID;
173181
174182 struct : ConfigurableGroup {
@@ -432,10 +440,7 @@ struct DeltaAnalysis {
432440 histos.add (" MCRecoEvent/centralitydistribution" , " Centrality distribution (MC);vCentFT0M;Entries" , kTH1F , {centAxis});
433441 }
434442
435- // ── MC reconstructed event mixing: histograms (gated by the dedicated MC mixing switch,
436- // independent from doprocessMC / doprocessMixedEvent). Mirrors the DATA EM histograms
437- // one-to-one but lives under its own AnalysisMCReco / THnSparseMCReco keys so downstream
438- // scripts can never confuse DATA-EM with MCReco-EM. ─────────────────────────────────────
443+ // ── MC reconstructed event mixing: histograms (gated by the dedicated MC mixing switch)
439444 if (mixingCfg.enableMCEventMixing ) {
440445 histos.add (" AnalysisMCReco/hDeltaPlusPlusInvMassEM" , " #Delta^{++} invariant mass - MC reconstructed event mixing" , kTH2F , {ptAxis, massAxis});
441446 histos.add (" AnalysisMCReco/hAntiDeltaPlusPlusInvMassEM" , " #bar{#Delta}^{++} invariant mass - MC reconstructed event mixing" , kTH2F , {ptAxis, massAxis});
@@ -447,7 +452,6 @@ struct DeltaAnalysis {
447452 histos.add (" THnSparseMCReco/hDeltaZeroEM" , " THnSparse #Delta^{0} MC reconstructed event mixing" , kTHnSparseF , {massAxis, ptAxis, centAxis, rapAxis});
448453 histos.add (" THnSparseMCReco/hAntiDeltaZeroEM" , " THnSparse #bar{#Delta}^{0} MC reconstructed event mixing" , kTHnSparseF , {massAxis, ptAxis, centAxis, rapAxis});
449454
450- // Minimal debug QA: verifies MC mixing actually ran (non-zero when enabled and MC data flows through it).
451455 histos.add (" QAMC/EventMixing/hMixedEventPairs" , " Number of MC mixed-event collision pairs processed" , kTH1F , {{1 , 0 .5f , 1 .5f }});
452456 histos.add (" QAMC/EventMixing/hMixedEventPairsByCentrality" , " MC mixed-event collision pairs vs centrality" , kTH1F , {centAxis});
453457 }
@@ -472,9 +476,6 @@ struct DeltaAnalysis {
472476 histos.add (" MCGenQA/hGenPionAntiDeltaPlusPlus" , " Gen pion from #bar{#Delta}^{++}" , kTH1F , {ptAxis});
473477 histos.add (" MCGenQA/hGenPionDeltaZero" , " Gen pion from #Delta^{0}" , kTH1F , {ptAxis});
474478 histos.add (" MCGenQA/hGenPionAntiDeltaZero" , " Gen pion from #bar{#Delta}^{0}" , kTH1F , {ptAxis});
475-
476- // Generated-Delta cut flow. 0=All generated, 1=producedByGenerator, 2=truth vertex-z,
477- // 3=truth INEL>0, 4=PDG, 5=rapidity, 6=decay channel, 7=final generated histogram.
478479 histos.add (" MCGenQA/hGenDeltaCutFlow" , " Generated #Delta cut flow" , kTH1F , {{8 , -0 .5f , 7 .5f }});
479480
480481 histos.add (" MCGen/GeneratedDelta_EventAccepted/hDeltaPlusPlusInvMass" , " #Delta^{++} generated, event-accepted" , kTH2F , {ptAxis, massAxis});
@@ -497,9 +498,6 @@ struct DeltaAnalysis {
497498 }
498499
499500 // ── Event-level cut-flow (QA-only) histograms ───────────────────────────────────────────
500- // These are pure bookkeeping: they record how many events survive each existing selection
501- // step (already implemented in passesEventSelectionImpl<Tag>(), isTruthInelGt0(), and
502- // processEventFactor()) and do not themselves apply, add, or alter any selection.
503501 {
504502 histos.add (" CutFlow/Data/hEventCutFlow" , " Data event cut flow" , kTH1F , {{9 , -0 .5f , 8 .5f }});
505503 auto hDataCutFlow = histos.get <TH1 >(HIST (" CutFlow/Data/hEventCutFlow" ));
@@ -622,8 +620,6 @@ struct DeltaAnalysis {
622620 return collision.multNTracksPVeta1 () > 0 ;
623621 }
624622
625- // Truth-level charged-primary identification, used only to build the truth-level INEL>0 event
626- // class (isTruthInelGt0 below).
627623 template <typename McParticleType>
628624 bool isChargedPrimaryMC (McParticleType const & mcPart)
629625 {
@@ -637,8 +633,6 @@ struct DeltaAnalysis {
637633 return std::abs (pdgParticle->Charge ()) > MinAbsCharge;
638634 }
639635
640- // Truth-level analogue of isRecoInelGt0() above - at least one charged primary within
641- // |eta| < 1 among the generated particles of a given MC collision.
642636 template <typename McParticleTableType>
643637 bool isTruthInelGt0 (McParticleTableType const & mcParticlesInCollision)
644638 {
@@ -710,6 +704,11 @@ struct DeltaAnalysis {
710704 }
711705 fillEventCutFlowBin<Tag>(7 .f ); // GoodZvtxFT0vsPV
712706
707+ if (evSel.cfgUseGoodITSLayersAll &&
708+ !collision.selection_bit (o2::aod::evsel::kIsGoodITSLayersAll )) {
709+ return false ;
710+ }
711+
713712 fillEventCutFlowBin<Tag>(8 .f ); // Final accepted event
714713 return true ;
715714 }
@@ -755,7 +754,7 @@ struct DeltaAnalysis {
755754 if (trackCuts.requirePrimaryTrack && !track.isPrimaryTrack ()) {
756755 return false ;
757756 }
758- if (trackCuts.requireGlobalTrackNoDCA && !track.isGlobalTrackWoDCA ()) {
757+ if (trackCuts.requireGlobalTrack && !track.isGlobalTrack ()) {
759758 return false ;
760759 }
761760 if (trackCuts.requirePVContributor && !track.isPVContributor ()) {
@@ -767,6 +766,14 @@ struct DeltaAnalysis {
767766 template <typename TrackType>
768767 bool passesProtonDCASelection (TrackType const & track)
769768 {
769+ if (dcaCuts.isApplyPtDepDCAxyCut ) {
770+ const float dcaConst = dcaCuts.dcaXYConst ;
771+ const float dcaCoeff = dcaCuts.dcaXYPtCoeff ;
772+ const float dcaExp = dcaCuts.dcaXYPtExponent ;
773+ const float maxDCAxy = dcaConst + dcaCoeff / std::pow (track.pt (), dcaExp);
774+ return (std::abs (track.dcaXY ()) < maxDCAxy) && (std::abs (track.dcaZ ()) < dcaCuts.cfgCutDCAz );
775+ }
776+
770777 const int nBins = static_cast <int >(mProtonDCAPtEdges .size ()) - 1 ;
771778 const float pt = track.pt ();
772779 bool passed = false ;
@@ -783,6 +790,14 @@ struct DeltaAnalysis {
783790 template <typename TrackType>
784791 bool passesPionDCASelection (TrackType const & track)
785792 {
793+ if (dcaCuts.isApplyPtDepDCAxyCut ) {
794+ const float dcaConst = dcaCuts.dcaXYConst ;
795+ const float dcaCoeff = dcaCuts.dcaXYPtCoeff ;
796+ const float dcaExp = dcaCuts.dcaXYPtExponent ;
797+ const float maxDCAxy = dcaConst + dcaCoeff / std::pow (track.pt (), dcaExp);
798+ return (std::abs (track.dcaXY ()) < maxDCAxy) && (std::abs (track.dcaZ ()) < dcaCuts.cfgCutDCAz );
799+ }
800+
786801 const int nBins = static_cast <int >(mPionDCAPtEdges .size ()) - 1 ;
787802 const float pt = track.pt ();
788803 bool passed = false ;
@@ -831,7 +846,8 @@ struct DeltaAnalysis {
831846 }
832847
833848 // Circular mode: joint TPC+TOF nSigma radius.
834- const float combinedNSigPr = tpcNSigPr * tpcNSigPr + tofNSigPr * tofNSigPr;
849+ const float shiftedTofNSigPr = track.tofNSigmaPr () - static_cast <float >(protonPID.shiftInNsigmaTOFProton );
850+ const float combinedNSigPr = tpcNSigPr * tpcNSigPr + shiftedTofNSigPr * shiftedTofNSigPr;
835851 const float combinedNSigPi = tpcNSigPi * tpcNSigPi + tofNSigPi * tofNSigPi;
836852 const auto circularCutSq = static_cast <float >(protonPID.combinedNSigmaCutProton * protonPID.combinedNSigmaCutProton );
837853 const float circularVetoCutSq = pidShared.tpcNSigmaVetoThreshold * pidShared.tpcNSigmaVetoThreshold +
@@ -888,7 +904,8 @@ struct DeltaAnalysis {
888904 }
889905
890906 // Circular mode: joint TPC+TOF nSigma radius.
891- const float combinedNSigPi = tpcNSigPi * tpcNSigPi + tofNSigPi * tofNSigPi;
907+ const float shiftedTofNSigPi = track.tofNSigmaPi () - static_cast <float >(pionPID.shiftInNsigmaTOFPion );
908+ const float combinedNSigPi = tpcNSigPi * tpcNSigPi + shiftedTofNSigPi * shiftedTofNSigPi;
892909 const float combinedNSigPr = tpcNSigPr * tpcNSigPr + tofNSigPr * tofNSigPr;
893910 const auto circularCutSq = static_cast <float >(pionPID.combinedNSigmaCutPion * pionPID.combinedNSigmaCutPion );
894911 const float circularVetoCutSq = pidShared.tpcNSigmaVetoThreshold * pidShared.tpcNSigmaVetoThreshold +
@@ -928,7 +945,7 @@ struct DeltaAnalysis {
928945 histos.fill (HIST (" QAafter/Proton/tpcCrossedRowsVsPt" ), pt, track.tpcNClsCrossedRows ());
929946 histos.fill (HIST (" QAafter/Proton/tpcClustersFoundVsPt" ), pt, track.tpcNClsFound ());
930947 if (!pidShared.useTPCOnlyPID && track.hasTOF ()) {
931- const float tofNSigPr = track.tofNSigmaPr ();
948+ const float tofNSigPr = track.tofNSigmaPr () - static_cast < float >(protonPID. shiftInNsigmaTOFProton ) ;
932949 histos.fill (HIST (" QAafter/Proton/tofNSigmaVsMomentum" ), totalMomentum, tofNSigPr);
933950 histos.fill (HIST (" QAafter/Proton/tofNSigmaVsPt" ), pt, tofNSigPr);
934951 histos.fill (HIST (" QAafter/Proton/tofNSigmaVsCentrality" ), centralityPercent, tofNSigPr);
@@ -954,7 +971,7 @@ struct DeltaAnalysis {
954971 histos.fill (HIST (" QAafter/Pion/tpcCrossedRowsVsPt" ), pt, track.tpcNClsCrossedRows ());
955972 histos.fill (HIST (" QAafter/Pion/tpcClustersFoundVsPt" ), pt, track.tpcNClsFound ());
956973 if (!pidShared.useTPCOnlyPID && track.hasTOF ()) {
957- const float tofNSigPi = track.tofNSigmaPi ();
974+ const float tofNSigPi = track.tofNSigmaPi () - static_cast < float >(pionPID. shiftInNsigmaTOFPion ) ;
958975 histos.fill (HIST (" QAafter/Pion/tofNSigmaVsMomentum" ), totalMomentum, tofNSigPi);
959976 histos.fill (HIST (" QAafter/Pion/tofNSigmaVsPt" ), pt, tofNSigPi);
960977 histos.fill (HIST (" QAafter/Pion/tofNSigmaVsCentrality" ), centralityPercent, tofNSigPi);
@@ -980,7 +997,7 @@ struct DeltaAnalysis {
980997 histos.fill (HIST (" QAMC/Proton/tpcCrossedRowsVsPt" ), pt, track.tpcNClsCrossedRows ());
981998 histos.fill (HIST (" QAMC/Proton/tpcClustersFoundVsPt" ), pt, track.tpcNClsFound ());
982999 if (!pidShared.useTPCOnlyPID && track.hasTOF ()) {
983- const float tofNSigPr = track.tofNSigmaPr ();
1000+ const float tofNSigPr = track.tofNSigmaPr () - static_cast < float >(protonPID. shiftInNsigmaTOFProton ) ;
9841001 histos.fill (HIST (" QAMC/Proton/tofNSigmaVsMomentum" ), totalMomentum, tofNSigPr);
9851002 histos.fill (HIST (" QAMC/Proton/tofNSigmaVsPt" ), pt, tofNSigPr);
9861003 histos.fill (HIST (" QAMC/Proton/tofNSigmaVsCentrality" ), centralityPercent, tofNSigPr);
@@ -1006,7 +1023,7 @@ struct DeltaAnalysis {
10061023 histos.fill (HIST (" QAMC/Pion/tpcCrossedRowsVsPt" ), pt, track.tpcNClsCrossedRows ());
10071024 histos.fill (HIST (" QAMC/Pion/tpcClustersFoundVsPt" ), pt, track.tpcNClsFound ());
10081025 if (!pidShared.useTPCOnlyPID && track.hasTOF ()) {
1009- const float tofNSigPi = track.tofNSigmaPi ();
1026+ const float tofNSigPi = track.tofNSigmaPi () - static_cast < float >(pionPID. shiftInNsigmaTOFPion ) ;
10101027 histos.fill (HIST (" QAMC/Pion/tofNSigmaVsMomentum" ), totalMomentum, tofNSigPi);
10111028 histos.fill (HIST (" QAMC/Pion/tofNSigmaVsPt" ), pt, tofNSigPi);
10121029 histos.fill (HIST (" QAMC/Pion/tofNSigmaVsCentrality" ), centralityPercent, tofNSigPi);
@@ -1889,7 +1906,7 @@ struct DeltaAnalysis {
18891906 histos.fill (HIST (" EfficiencyQA/hGeneratedEventCutFlow" ), 1 .f ); // |Vz| accepted
18901907
18911908 const bool truthInelGt0 = isTruthInelGt0 (mcParticles);
1892- if (evSel.cfgRequireRecoINELgt0 && !truthInelGt0) {
1909+ if (evSel.cfgApplyMCTruthINELgt0 && !truthInelGt0) {
18931910 return ;
18941911 }
18951912 histos.fill (HIST (" CutFlow/MCGen/hEventCutFlow" ), 2 .f ); // Truth INEL>0
@@ -1898,8 +1915,6 @@ struct DeltaAnalysis {
18981915 histos.fill (HIST (" CutFlow/MCGen/hEventCutFlow" ), 4 .f ); // Final generated event
18991916 histos.fill (HIST (" EfficiencyQA/hGeneratedEventCutFlow" ), 3 .f ); // Final generated event
19001917
1901- // ── MODIFIED BLOCK (per user request): centrality-source switch for generated Delta ────
1902- // Added: evSel.cfgUseMCTruthCentrality (see Configurable added in evSel group above).
19031918 bool hasAcceptedReco = false ;
19041919 float genCentrality = mcCollision.centFT0M ();
19051920
@@ -2062,7 +2077,7 @@ struct DeltaAnalysis {
20622077 histos.fill (HIST (" CutFlow/EventFactor/hEventAcceptedCutFlow" ), 1 .f ); // |Vz| < cfgCutVertex
20632078
20642079 auto mcPartsThisColl = mcParticles.sliceBy (perMcCollisionDelta, mcCollision.globalIndex ());
2065- if (evSel.cfgRequireRecoINELgt0 && !isTruthInelGt0 (mcPartsThisColl)) {
2080+ if (evSel.cfgApplyMCTruthINELgt0 && !isTruthInelGt0 (mcPartsThisColl)) {
20662081 continue ;
20672082 }
20682083 histos.fill (HIST (" CutFlow/EventFactor/hEventAcceptedCutFlow" ), 2 .f ); // Truth INEL>0
@@ -2083,10 +2098,7 @@ struct DeltaAnalysis {
20832098 if (hasAcceptedReco) {
20842099 histos.fill (HIST (" CutFlow/EventFactor/hEventAcceptedCutFlow" ), 4 .f ); // Associated reco collision passes event selection
20852100 histos.fill (HIST (" CutFlow/EventFactor/hEventAcceptedCutFlow" ), 5 .f ); // Final EventAccepted
2086- // Truth-binned: denominator for event_loss = hEventsGenAccepted / hEventsGenAll (unchanged).
20872101 histos.fill (HIST (" EventFactor/hEventsGenAccepted" ), truthCentrality);
2088- // NEW - reco-binned: numerator for event_splitting = hEventsGenAcceptedReco / hRecoEvents,
2089- // now on the same (reconstructed) centrality axis as hRecoEvents.
20902102 histos.fill (HIST (" EventFactor/hEventsGenAcceptedReco" ), itCent->second );
20912103 }
20922104 }
0 commit comments