From 7da79a92071219b3e28808459dee37c604659dc4 Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Thu, 15 Oct 2026 14:57:30 +0530 Subject: [PATCH 1/8] Lambda-Proton Balance function - Update 7 --- .../Tasks/lambdaProtonBalanceFunction.cxx | 58 ++++++++++++------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index 83aae01ed99..76ce5e37885 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -392,7 +392,7 @@ struct LambdaProtonBalanceFunction { } // QA-only: true => pair would survive the q_inv cut, regardless of the cUseQinvCut master switch. - // Used ONLY for the "After_qinvCut" QA histograms so they always show the mathematical effect of the cut. + // Used for ALL "After_qinvCut" QA histograms (PP, pAp, App, ApAp, LP-family, LL-family) so they always show the mathematical effect of the cut. // Physics logic must keep using failsQinvCut(). bool passesQinvQA(float qinv) const { return qinv > cQinvCutValue.value; } @@ -3165,11 +3165,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted Lambda-proton pair float qinvLP = 0.0f; { - const float dauPmag = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); + const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); const float pprmag = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); - const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); + const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); const float Eppr = std::sqrt(pprmag * pprmag + kMassProton * kMassProton); - qinvLP = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau, primProton.px(), primProton.py(), primProton.pz(), Eppr); + qinvLP = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primProton.px(), primProton.py(), primProton.pz(), Eppr); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvLP); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3191,6 +3191,10 @@ struct LambdaProtonBalanceFunction { const float pprmag_3d = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); const float Eppr_3d = std::sqrt(pprmag_3d * pprmag_3d + kMassProton * kMassProton); const float qinvLP_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr_3d); + // q_inv using Lambda daughter proton (kMassProton hypothesis), only for *_dau histograms + const float dauPmag_3d = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); + const float Edau_3d = std::sqrt(dauPmag_3d * dauPmag_3d + kMassProton * kMassProton); + const float qinvLP_dau = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr_3d); // Angular variables w.r.t. Lambda daughter proton const float dPhi_dau_p = RecoDecay::constrainAngle((v0PosDau.phi() - primProton.phi()), -PIHalf3D); const float dEta_dau_p = v0PosDau.eta() - primProton.eta(); @@ -3198,10 +3202,10 @@ struct LambdaProtonBalanceFunction { const float dY_dau_p = yDauP - yPrimP; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_Lp"), qinvLP_V0, dPhi_V0_p, dEta_V0_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_Lp_dau"), qinvLP, dPhi_dau_p, dEta_dau_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_Lp_dau"), qinvLP_dau, dPhi_dau_p, dEta_dau_p); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_Lp"), qinvLP_V0, dPhi_V0_p, dY_V0_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_Lp_dau"), qinvLP, dPhi_dau_p, dY_dau_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_Lp_dau"), qinvLP_dau, dPhi_dau_p, dY_dau_p); } // QA3/SplitTrackQA: close-pair block for daughter-overlap diagnosed split tracks { @@ -3260,11 +3264,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted Lambda-antiproton pair float qinvLAp = 0.0f; { - const float dauPmag = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); + const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); const float paprmag = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); - const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); + const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); const float Epapr = std::sqrt(paprmag * paprmag + kMassProton * kMassProton); - qinvLAp = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr); + qinvLAp = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvLAp); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3286,6 +3290,10 @@ struct LambdaProtonBalanceFunction { const float paprmag_3dL = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); const float Epapr_3dL = std::sqrt(paprmag_3dL * paprmag_3dL + kMassProton * kMassProton); const float qinvLAp_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0_3dL, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr_3dL); + // q_inv using Lambda daughter proton (kMassProton hypothesis), only for *_dau histograms + const float dauPmag_3dL = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); + const float Edau_3dL = std::sqrt(dauPmag_3dL * dauPmag_3dL + kMassProton * kMassProton); + const float qinvLAp_dau = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau_3dL, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr_3dL); // Angular variables w.r.t. Lambda daughter proton const float dPhi_dau_ap = RecoDecay::constrainAngle((v0PosDau.phi() - primAntiProton.phi()), -PIHalf3D); const float dEta_dau_ap = v0PosDau.eta() - primAntiProton.eta(); @@ -3293,10 +3301,10 @@ struct LambdaProtonBalanceFunction { const float dY_dau_ap = yDauPL - yPrimAp; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_LAp"), qinvLAp_V0, dPhi_V0_ap, dEta_V0_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_LAp_dau"), qinvLAp, dPhi_dau_ap, dEta_dau_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_LAp_dau"), qinvLAp_dau, dPhi_dau_ap, dEta_dau_ap); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_LAp"), qinvLAp_V0, dPhi_V0_ap, dY_V0_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_LAp_dau"), qinvLAp, dPhi_dau_ap, dY_dau_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_LAp_dau"), qinvLAp_dau, dPhi_dau_ap, dY_dau_ap); } // QA3/RawPairDensity: Lambda-antiproton → same LP histogram { @@ -3410,11 +3418,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted AntiLambda-proton pair float qinvALp = 0.0f; { - const float dauPmag = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); + const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); const float pprmag3 = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); - const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); + const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); const float Eppr3 = std::sqrt(pprmag3 * pprmag3 + kMassProton * kMassProton); - qinvALp = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), Edau, primProton.px(), primProton.py(), primProton.pz(), Eppr3); + qinvALp = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primProton.px(), primProton.py(), primProton.pz(), Eppr3); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvALp); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3436,6 +3444,10 @@ struct LambdaProtonBalanceFunction { const float pprmag3_3d = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); const float Eppr3_3d = std::sqrt(pprmag3_3d * pprmag3_3d + kMassProton * kMassProton); const float qinvALp_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), EalL_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr3_3d); + // q_inv using AntiLambda daughter antiproton (kMassProton hypothesis), only for *_dau histograms + const float dauPmagAL_3d = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); + const float EdauAL_3d = std::sqrt(dauPmagAL_3d * dauPmagAL_3d + kMassProton * kMassProton); + const float qinvALp_dau = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), EdauAL_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr3_3d); // Angular variables w.r.t. AntiLambda daughter antiproton const float dPhi_dauAL_p = RecoDecay::constrainAngle((v0NegDau.phi() - primProton.phi()), -PIHalf3D); const float dEta_dauAL_p = v0NegDau.eta() - primProton.eta(); @@ -3443,10 +3455,10 @@ struct LambdaProtonBalanceFunction { const float dY_dauAL_p = yDauAL - yPrimP3; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALp"), qinvALp_V0, dPhi_AL_p, dEta_AL_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALp_dau"), qinvALp, dPhi_dauAL_p, dEta_dauAL_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALp_dau"), qinvALp_dau, dPhi_dauAL_p, dEta_dauAL_p); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALp"), qinvALp_V0, dPhi_AL_p, dY_AL_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALp_dau"), qinvALp, dPhi_dauAL_p, dY_dauAL_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALp_dau"), qinvALp_dau, dPhi_dauAL_p, dY_dauAL_p); } // QA3/RawPairDensity: AntiLambda-proton → same LP histogram { @@ -3488,11 +3500,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted AntiLambda-antiproton pair float qinvALAp = 0.0f; { - const float dauPmag = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); + const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); const float paprmag2 = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); - const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); + const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); const float Epapr2 = std::sqrt(paprmag2 * paprmag2 + kMassProton * kMassProton); - qinvALAp = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), Edau, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2); + qinvALAp = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvALAp); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3514,6 +3526,10 @@ struct LambdaProtonBalanceFunction { const float paprmag2_3d = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); const float Epapr2_3d = std::sqrt(paprmag2_3d * paprmag2_3d + kMassProton * kMassProton); const float qinvALAp_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), EalL2_3d, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2_3d); + // q_inv using AntiLambda daughter antiproton (kMassProton hypothesis), only for *_dau histograms + const float dauPmagAL2_3d = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); + const float EdauAL2_3d = std::sqrt(dauPmagAL2_3d * dauPmagAL2_3d + kMassProton * kMassProton); + const float qinvALAp_dau = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), EdauAL2_3d, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2_3d); // Angular variables w.r.t. AntiLambda daughter antiproton const float dPhi_dauAL_ap = RecoDecay::constrainAngle((v0NegDau.phi() - primAntiProton.phi()), -PIHalf3D); const float dEta_dauAL_ap = v0NegDau.eta() - primAntiProton.eta(); @@ -3521,10 +3537,10 @@ struct LambdaProtonBalanceFunction { const float dY_dauAL_ap = yDauAL2 - yPrimAp2; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALAp"), qinvALAp_V0, dPhi_AL_ap, dEta_AL_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALAp_dau"), qinvALAp, dPhi_dauAL_ap, dEta_dauAL_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALAp_dau"), qinvALAp_dau, dPhi_dauAL_ap, dEta_dauAL_ap); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALAp"), qinvALAp_V0, dPhi_AL_ap, dY_AL_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALAp_dau"), qinvALAp, dPhi_dauAL_ap, dY_dauAL_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALAp_dau"), qinvALAp_dau, dPhi_dauAL_ap, dY_dauAL_ap); } // QA3/SplitTrackQA: close-pair block for daughter-overlap diagnosed split tracks { From 5952b8972369d02b131a3879b30d4d51e758c332 Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Thu, 15 Oct 2026 15:23:41 +0530 Subject: [PATCH 2/8] Retriggering --- .../Tasks/lambdaProtonBalanceFunction.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index 76ce5e37885..01935edb783 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -3858,7 +3858,7 @@ struct LambdaProtonBalanceFunction { registryOther.fill(HIST("hNPairs_AntiLambda_PrimProton"), static_cast(nPairs_AntiLambda_PrimProton)); registryOther.fill(HIST("hNPairs_AntiLambda_PrimAntiProton"), static_cast(nPairs_AntiLambda_PrimAntiProton)); } - // ── Run-level summary printed once at the end of the analysis job ───── + // ── Run-level summary printed once at the end of the analysis job ──── // Called automatically by the O2 framework after all events are processed. // Prints totals accumulated in runTotalProtonBeforeVeto / runTotalProtonRemovedVeto. void endOfStream(EndOfStreamContext const&) From 7527e17fbfd9aa1f6ea7ea1101b528831c949c5f Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Thu, 15 Oct 2026 17:15:46 +0530 Subject: [PATCH 3/8] rechecking the build error with old code --- .../Tasks/lambdaProtonBalanceFunction.cxx | 62 +++++++------------ 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index 01935edb783..4a85f247d0e 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -392,7 +392,7 @@ struct LambdaProtonBalanceFunction { } // QA-only: true => pair would survive the q_inv cut, regardless of the cUseQinvCut master switch. - // Used for ALL "After_qinvCut" QA histograms (PP, pAp, App, ApAp, LP-family, LL-family) so they always show the mathematical effect of the cut. + // Used ONLY for the "After_qinvCut" QA histograms so they always show the mathematical effect of the cut. // Physics logic must keep using failsQinvCut(). bool passesQinvQA(float qinv) const { return qinv > cQinvCutValue.value; } @@ -3165,11 +3165,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted Lambda-proton pair float qinvLP = 0.0f; { - const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); + const float dauPmag = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); const float pprmag = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); - const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); + const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); const float Eppr = std::sqrt(pprmag * pprmag + kMassProton * kMassProton); - qinvLP = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primProton.px(), primProton.py(), primProton.pz(), Eppr); + qinvLP = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau, primProton.px(), primProton.py(), primProton.pz(), Eppr); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvLP); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3191,10 +3191,6 @@ struct LambdaProtonBalanceFunction { const float pprmag_3d = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); const float Eppr_3d = std::sqrt(pprmag_3d * pprmag_3d + kMassProton * kMassProton); const float qinvLP_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr_3d); - // q_inv using Lambda daughter proton (kMassProton hypothesis), only for *_dau histograms - const float dauPmag_3d = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); - const float Edau_3d = std::sqrt(dauPmag_3d * dauPmag_3d + kMassProton * kMassProton); - const float qinvLP_dau = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr_3d); // Angular variables w.r.t. Lambda daughter proton const float dPhi_dau_p = RecoDecay::constrainAngle((v0PosDau.phi() - primProton.phi()), -PIHalf3D); const float dEta_dau_p = v0PosDau.eta() - primProton.eta(); @@ -3202,10 +3198,10 @@ struct LambdaProtonBalanceFunction { const float dY_dau_p = yDauP - yPrimP; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_Lp"), qinvLP_V0, dPhi_V0_p, dEta_V0_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_Lp_dau"), qinvLP_dau, dPhi_dau_p, dEta_dau_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_Lp_dau"), qinvLP, dPhi_dau_p, dEta_dau_p); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_Lp"), qinvLP_V0, dPhi_V0_p, dY_V0_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_Lp_dau"), qinvLP_dau, dPhi_dau_p, dY_dau_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_Lp_dau"), qinvLP, dPhi_dau_p, dY_dau_p); } // QA3/SplitTrackQA: close-pair block for daughter-overlap diagnosed split tracks { @@ -3264,11 +3260,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted Lambda-antiproton pair float qinvLAp = 0.0f; { - const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); + const float dauPmag = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); const float paprmag = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); - const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); + const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); const float Epapr = std::sqrt(paprmag * paprmag + kMassProton * kMassProton); - qinvLAp = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr); + qinvLAp = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvLAp); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3290,10 +3286,6 @@ struct LambdaProtonBalanceFunction { const float paprmag_3dL = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); const float Epapr_3dL = std::sqrt(paprmag_3dL * paprmag_3dL + kMassProton * kMassProton); const float qinvLAp_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0_3dL, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr_3dL); - // q_inv using Lambda daughter proton (kMassProton hypothesis), only for *_dau histograms - const float dauPmag_3dL = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); - const float Edau_3dL = std::sqrt(dauPmag_3dL * dauPmag_3dL + kMassProton * kMassProton); - const float qinvLAp_dau = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau_3dL, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr_3dL); // Angular variables w.r.t. Lambda daughter proton const float dPhi_dau_ap = RecoDecay::constrainAngle((v0PosDau.phi() - primAntiProton.phi()), -PIHalf3D); const float dEta_dau_ap = v0PosDau.eta() - primAntiProton.eta(); @@ -3301,10 +3293,10 @@ struct LambdaProtonBalanceFunction { const float dY_dau_ap = yDauPL - yPrimAp; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_LAp"), qinvLAp_V0, dPhi_V0_ap, dEta_V0_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_LAp_dau"), qinvLAp_dau, dPhi_dau_ap, dEta_dau_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_LAp_dau"), qinvLAp, dPhi_dau_ap, dEta_dau_ap); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_LAp"), qinvLAp_V0, dPhi_V0_ap, dY_V0_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_LAp_dau"), qinvLAp_dau, dPhi_dau_ap, dY_dau_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_LAp_dau"), qinvLAp, dPhi_dau_ap, dY_dau_ap); } // QA3/RawPairDensity: Lambda-antiproton → same LP histogram { @@ -3418,11 +3410,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted AntiLambda-proton pair float qinvALp = 0.0f; { - const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); + const float dauPmag = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); const float pprmag3 = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); - const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); + const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); const float Eppr3 = std::sqrt(pprmag3 * pprmag3 + kMassProton * kMassProton); - qinvALp = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primProton.px(), primProton.py(), primProton.pz(), Eppr3); + qinvALp = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), Edau, primProton.px(), primProton.py(), primProton.pz(), Eppr3); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvALp); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3444,10 +3436,6 @@ struct LambdaProtonBalanceFunction { const float pprmag3_3d = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); const float Eppr3_3d = std::sqrt(pprmag3_3d * pprmag3_3d + kMassProton * kMassProton); const float qinvALp_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), EalL_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr3_3d); - // q_inv using AntiLambda daughter antiproton (kMassProton hypothesis), only for *_dau histograms - const float dauPmagAL_3d = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); - const float EdauAL_3d = std::sqrt(dauPmagAL_3d * dauPmagAL_3d + kMassProton * kMassProton); - const float qinvALp_dau = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), EdauAL_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr3_3d); // Angular variables w.r.t. AntiLambda daughter antiproton const float dPhi_dauAL_p = RecoDecay::constrainAngle((v0NegDau.phi() - primProton.phi()), -PIHalf3D); const float dEta_dauAL_p = v0NegDau.eta() - primProton.eta(); @@ -3455,10 +3443,10 @@ struct LambdaProtonBalanceFunction { const float dY_dauAL_p = yDauAL - yPrimP3; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALp"), qinvALp_V0, dPhi_AL_p, dEta_AL_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALp_dau"), qinvALp_dau, dPhi_dauAL_p, dEta_dauAL_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALp_dau"), qinvALp, dPhi_dauAL_p, dEta_dauAL_p); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALp"), qinvALp_V0, dPhi_AL_p, dY_AL_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALp_dau"), qinvALp_dau, dPhi_dauAL_p, dY_dauAL_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALp_dau"), qinvALp, dPhi_dauAL_p, dY_dauAL_p); } // QA3/RawPairDensity: AntiLambda-proton → same LP histogram { @@ -3500,11 +3488,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted AntiLambda-antiproton pair float qinvALAp = 0.0f; { - const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); + const float dauPmag = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); const float paprmag2 = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); - const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); + const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); const float Epapr2 = std::sqrt(paprmag2 * paprmag2 + kMassProton * kMassProton); - qinvALAp = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2); + qinvALAp = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), Edau, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvALAp); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3526,10 +3514,6 @@ struct LambdaProtonBalanceFunction { const float paprmag2_3d = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); const float Epapr2_3d = std::sqrt(paprmag2_3d * paprmag2_3d + kMassProton * kMassProton); const float qinvALAp_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), EalL2_3d, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2_3d); - // q_inv using AntiLambda daughter antiproton (kMassProton hypothesis), only for *_dau histograms - const float dauPmagAL2_3d = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); - const float EdauAL2_3d = std::sqrt(dauPmagAL2_3d * dauPmagAL2_3d + kMassProton * kMassProton); - const float qinvALAp_dau = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), EdauAL2_3d, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2_3d); // Angular variables w.r.t. AntiLambda daughter antiproton const float dPhi_dauAL_ap = RecoDecay::constrainAngle((v0NegDau.phi() - primAntiProton.phi()), -PIHalf3D); const float dEta_dauAL_ap = v0NegDau.eta() - primAntiProton.eta(); @@ -3537,10 +3521,10 @@ struct LambdaProtonBalanceFunction { const float dY_dauAL_ap = yDauAL2 - yPrimAp2; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALAp"), qinvALAp_V0, dPhi_AL_ap, dEta_AL_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALAp_dau"), qinvALAp_dau, dPhi_dauAL_ap, dEta_dauAL_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALAp_dau"), qinvALAp, dPhi_dauAL_ap, dEta_dauAL_ap); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALAp"), qinvALAp_V0, dPhi_AL_ap, dY_AL_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALAp_dau"), qinvALAp_dau, dPhi_dauAL_ap, dY_dauAL_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALAp_dau"), qinvALAp, dPhi_dauAL_ap, dY_dauAL_ap); } // QA3/SplitTrackQA: close-pair block for daughter-overlap diagnosed split tracks { @@ -3858,7 +3842,7 @@ struct LambdaProtonBalanceFunction { registryOther.fill(HIST("hNPairs_AntiLambda_PrimProton"), static_cast(nPairs_AntiLambda_PrimProton)); registryOther.fill(HIST("hNPairs_AntiLambda_PrimAntiProton"), static_cast(nPairs_AntiLambda_PrimAntiProton)); } - // ── Run-level summary printed once at the end of the analysis job ──── + // ── Run-level summary printed once at the end of the analysis job ───── // Called automatically by the O2 framework after all events are processed. // Prints totals accumulated in runTotalProtonBeforeVeto / runTotalProtonRemovedVeto. void endOfStream(EndOfStreamContext const&) @@ -3885,7 +3869,7 @@ struct LambdaProtonBalanceFunction { LOG(info) << "==============================================="; LOG(info) << ""; } - // ───────────────────────────────────────────────────────────────────── + // ───────────────────────xx────────────────────────────────────────────── }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 29ea0b9b38de33a4827728c92b9a6274c9315ba3 Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Thu, 15 Oct 2026 18:38:14 +0530 Subject: [PATCH 4/8] reintroducing new code again. --- .../Tasks/lambdaProtonBalanceFunction.cxx | 173 ++++-------------- 1 file changed, 38 insertions(+), 135 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index 4a85f247d0e..51b3a29335b 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -88,7 +88,6 @@ struct CentRho2Set { struct LambdaProtonBalanceFunction { HistogramRegistry registryLambda{"Lambda_invMass", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry registryLambdaExtended{"Lambda_invMassExtended", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryRho{"rho1ANDrho2_LP", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryCent{"rho1ANDrho2_LP_CentralityBased", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryOther{"Other_Hists", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -101,19 +100,6 @@ struct LambdaProtonBalanceFunction { // Contains per-event distributions of N_before, N_after, N_removed, fraction. HistogramRegistry registryProtonVetoQA{"ProtonVetoQA", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - // ════════════════════════════════════════════════════════════════════════ - // Static compile-time constants (not non-static data members: do not count - // toward the O2 StructToTuple arity). - // ════════════════════════════════════════════════════════════════════════ - static constexpr int kExtNyBins = 2; - static constexpr int kExtNptBins = 25; - static constexpr float kExtYMin = -0.8f; - static constexpr float kExtYMax = -0.6f; - static constexpr float kExtYStep = 0.1f; - static constexpr float kExtPtMin = 0.0f; - static constexpr float kExtPtMax = 2.5f; - static constexpr float kExtPtStep = 0.1f; - // ════════════════════════════════════════════════════════════════════════ // TaskState — ordinary C++ runtime/implementation state. // Grouped into ONE nested object so that the number of direct data members of @@ -133,17 +119,6 @@ struct LambdaProtonBalanceFunction { std::shared_ptr hMassLambdaMerged; std::shared_ptr hMassAntiLambdaMerged; - // ════════════════════════════════════════════════════════════════════════ - // SECTION A2— Extended invariant-mass histograms (y × pT grid) - // hMassLambdaExtended[iY][iPt] → Lambda_invMassExtended/Lambda/ - // hMassAntiLambdaExtended[iY][iPt] → Lambda_invMassExtended/AntiLambda/ - // Rapidity bins (kExtNyBins = 2): [-0.8,-0.7), [-0.7,-0.6] - // pT bins (kExtNptBins = 25): [0.0,0.1), [0.1,0.2), ..., [2.4,2.5] - // ════════════════════════════════════════════════════════════════════════ - - std::vector>> hMassLambdaExtended; - std::vector>> hMassAntiLambdaExtended; - // ════════════════════════════════════════════════════════════════════════ // SECTION C — rho2 rapidity-space histograms, filled with unrolledIndexY(y, phi). // Naming: hRho2__y_AllPt. @@ -392,7 +367,7 @@ struct LambdaProtonBalanceFunction { } // QA-only: true => pair would survive the q_inv cut, regardless of the cUseQinvCut master switch. - // Used ONLY for the "After_qinvCut" QA histograms so they always show the mathematical effect of the cut. + // Used for ALL "After_qinvCut" QA histograms (PP, pAp, App, ApAp, LP-family, LL-family) so they always show the mathematical effect of the cut. // Physics logic must keep using failsQinvCut(). bool passesQinvQA(float qinv) const { return qinv > cQinvCutValue.value; } @@ -2016,53 +1991,6 @@ struct LambdaProtonBalanceFunction { } // ───────────────────────────────────────────────────────────────────── - // ── Extended y × pT invariant-mass histograms ───────────────────────── - // Rapidity bins: 2 bins from -0.8 to -0.6 in steps of 0.1 - // pT bins: 25 bins from 0.0 to 2.5 in steps of 0.1 - // Folder structure: - // Lambda_invMassExtended/Lambda/hMassLambda_yBinXX_ptBinYY - // Lambda_invMassExtended/AntiLambda/hMassAntiLambda_yBinXX_ptBinYY - state.hMassLambdaExtended.clear(); - state.hMassAntiLambdaExtended.clear(); - state.hMassLambdaExtended.resize(kExtNyBins); - state.hMassAntiLambdaExtended.resize(kExtNyBins); - - for (int iY = 0; iY < kExtNyBins; ++iY) { - const float yLow = kExtYMin + iY * kExtYStep; - const float yHigh = yLow + kExtYStep; - // Last rapidity bin [-0.7,-0.6] has inclusive upper edge in filling logic - const bool lastYBin = (iY == kExtNyBins - 1); - const char* yUpBracket = lastYBin ? "<=" : "<"; - - state.hMassLambdaExtended[iY].resize(kExtNptBins); - state.hMassAntiLambdaExtended[iY].resize(kExtNptBins); - - for (int iPt = 0; iPt < kExtNptBins; ++iPt) { - const float ptLow = kExtPtMin + iPt * kExtPtStep; - const float ptHigh = ptLow + kExtPtStep; - // Last pT bin [2.4,2.5] has inclusive upper edge in filling logic - const bool lastPtBin = (iPt == kExtNptBins - 1); - const char* ptUpBracket = lastPtBin ? "<=" : "<"; - - // Lambda - state.hMassLambdaExtended[iY][iPt] = - registryLambdaExtended.add( - Form("Lambda/hMassLambda_yBin%02d_ptBin%02d", iY, iPt), - Form("#Lambda mass (no mass-window cut) | %.1f #leq y %s %.1f | %.1f #leq #it{p}_{T} %s %.1f GeV/#it{c};#it{M}_{inv} [GeV/#it{c}^{2}];Counts", - yLow, yUpBracket, yHigh, ptLow, ptUpBracket, ptHigh), - {HistType::kTH1F, {lambdaMassAxis}}); - - // AntiLambda - state.hMassAntiLambdaExtended[iY][iPt] = - registryLambdaExtended.add( - Form("AntiLambda/hMassAntiLambda_yBin%02d_ptBin%02d", iY, iPt), - Form("#bar{#Lambda} mass (no mass-window cut) | %.1f #leq y %s %.1f | %.1f #leq #it{p}_{T} %s %.1f GeV/#it{c};#it{M}_{inv} [GeV/#it{c}^{2}];Counts", - yLow, yUpBracket, yHigh, ptLow, ptUpBracket, ptHigh), - {HistType::kTH1F, {lambdaMassAxis}}); - } - } - // ───────────────────────────────────────────────────────────────────── - // ══════════════════════════════════════════════════════════════════════ // Centrality-differential histograms → top-level folder "rho1ANDrho2_LP_CentralityBased" // ══════════════════════════════════════════════════════════════════════ @@ -2461,7 +2389,6 @@ struct LambdaProtonBalanceFunction { // const float eta = v0.eta(); // VS Code: commented out unused variable. // const float pz = pt * std::sinh(eta); - const float y = v0DauPID_AsLambda ? v0.rapidity(1) : v0.rapidity(2); int bin = -1; for (size_t i = 0; i < state.ptEdges.size() - 1; ++i) { if (pt >= state.ptEdges[i] && pt < state.ptEdges[i + 1]) { @@ -2487,27 +2414,6 @@ struct LambdaProtonBalanceFunction { if (selLambda) { registryQaDetector.fill(HIST("Lambda/InvariantMass/MassCut/h2f_mass_vs_pt"), pt, v0.mLambda()); } - - // ── Extended y × pT Lambda invariant-mass fill ──────────────────── - // Use the same rapidity variable `y` computed above - // and the same pT variable `pt` = v0.pt() already in scope. - // Accept only -0.8 <= y <= -0.6 and 0.0 <= pT <= 2.5 GeV/c. - if (y >= kExtYMin && y <= kExtYMax && pt >= kExtPtMin && pt <= kExtPtMax) { - // Determine rapidity bin index - int iYext = static_cast((y - kExtYMin) / kExtYStep); - if (iYext >= kExtNyBins) { - iYext = kExtNyBins - 1; - } // clamp upper edge of last bin - // Determine pT bin index - int iPtext = static_cast((pt - kExtPtMin) / kExtPtStep); - if (iPtext >= kExtNptBins) { - iPtext = kExtNptBins - 1; - } // clamp upper edge of last bin - if (iYext >= 0 && iPtext >= 0) { - state.hMassLambdaExtended[iYext][iPtext]->Fill(v0.mLambda()); - } - } - // ───────────────────────────────────────────────────────────────── } if (v0DauPID_AsAntiLambda) { if (bin >= 0) { @@ -2522,25 +2428,6 @@ struct LambdaProtonBalanceFunction { if (selAntiLambda) { registryQaDetector.fill(HIST("AntiLambda/InvariantMass/MassCut/h2f_mass_vs_pt"), pt, v0.mAntiLambda()); } - - // ── Extended y × pT AntiLambda invariant-mass fill ──────────────── - // Use the same rapidity variable `y` computed above - // and the same pT variable `pt` = v0.pt() already in scope. - // Accept only -0.8 <= y <= -0.6 and 0.0 <= pT <= 2.5 GeV/c. - if (y >= kExtYMin && y <= kExtYMax && pt >= kExtPtMin && pt <= kExtPtMax) { - int iYext = static_cast((y - kExtYMin) / kExtYStep); - if (iYext >= kExtNyBins) { - iYext = kExtNyBins - 1; - } // clamp upper edge of last bin - int iPtext = static_cast((pt - kExtPtMin) / kExtPtStep); - if (iPtext >= kExtNptBins) { - iPtext = kExtNptBins - 1; - } // clamp upper edge of last bin - if (iYext >= 0 && iPtext >= 0) { - state.hMassAntiLambdaExtended[iYext][iPtext]->Fill(v0.mAntiLambda()); - } - } - // ───────────────────────────────────────────────────────────────── } // ───────────────────────────────────────────────────────────────── @@ -3165,11 +3052,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted Lambda-proton pair float qinvLP = 0.0f; { - const float dauPmag = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); + const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); const float pprmag = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); - const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); + const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); const float Eppr = std::sqrt(pprmag * pprmag + kMassProton * kMassProton); - qinvLP = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau, primProton.px(), primProton.py(), primProton.pz(), Eppr); + qinvLP = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primProton.px(), primProton.py(), primProton.pz(), Eppr); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvLP); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3191,6 +3078,10 @@ struct LambdaProtonBalanceFunction { const float pprmag_3d = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); const float Eppr_3d = std::sqrt(pprmag_3d * pprmag_3d + kMassProton * kMassProton); const float qinvLP_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr_3d); + // q_inv using Lambda daughter proton (kMassProton hypothesis), only for *_dau histograms + const float dauPmag_3d = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); + const float Edau_3d = std::sqrt(dauPmag_3d * dauPmag_3d + kMassProton * kMassProton); + const float qinvLP_dau = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr_3d); // Angular variables w.r.t. Lambda daughter proton const float dPhi_dau_p = RecoDecay::constrainAngle((v0PosDau.phi() - primProton.phi()), -PIHalf3D); const float dEta_dau_p = v0PosDau.eta() - primProton.eta(); @@ -3198,10 +3089,10 @@ struct LambdaProtonBalanceFunction { const float dY_dau_p = yDauP - yPrimP; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_Lp"), qinvLP_V0, dPhi_V0_p, dEta_V0_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_Lp_dau"), qinvLP, dPhi_dau_p, dEta_dau_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_Lp_dau"), qinvLP_dau, dPhi_dau_p, dEta_dau_p); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_Lp"), qinvLP_V0, dPhi_V0_p, dY_V0_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_Lp_dau"), qinvLP, dPhi_dau_p, dY_dau_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_Lp_dau"), qinvLP_dau, dPhi_dau_p, dY_dau_p); } // QA3/SplitTrackQA: close-pair block for daughter-overlap diagnosed split tracks { @@ -3260,11 +3151,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted Lambda-antiproton pair float qinvLAp = 0.0f; { - const float dauPmag = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); + const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); const float paprmag = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); - const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); + const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); const float Epapr = std::sqrt(paprmag * paprmag + kMassProton * kMassProton); - qinvLAp = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr); + qinvLAp = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvLAp); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3286,6 +3177,10 @@ struct LambdaProtonBalanceFunction { const float paprmag_3dL = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); const float Epapr_3dL = std::sqrt(paprmag_3dL * paprmag_3dL + kMassProton * kMassProton); const float qinvLAp_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0_3dL, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr_3dL); + // q_inv using Lambda daughter proton (kMassProton hypothesis), only for *_dau histograms + const float dauPmag_3dL = std::sqrt(v0PosDau.px() * v0PosDau.px() + v0PosDau.py() * v0PosDau.py() + v0PosDau.pz() * v0PosDau.pz()); + const float Edau_3dL = std::sqrt(dauPmag_3dL * dauPmag_3dL + kMassProton * kMassProton); + const float qinvLAp_dau = computeQinv(v0PosDau.px(), v0PosDau.py(), v0PosDau.pz(), Edau_3dL, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr_3dL); // Angular variables w.r.t. Lambda daughter proton const float dPhi_dau_ap = RecoDecay::constrainAngle((v0PosDau.phi() - primAntiProton.phi()), -PIHalf3D); const float dEta_dau_ap = v0PosDau.eta() - primAntiProton.eta(); @@ -3293,10 +3188,10 @@ struct LambdaProtonBalanceFunction { const float dY_dau_ap = yDauPL - yPrimAp; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_LAp"), qinvLAp_V0, dPhi_V0_ap, dEta_V0_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_LAp_dau"), qinvLAp, dPhi_dau_ap, dEta_dau_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_LAp_dau"), qinvLAp_dau, dPhi_dau_ap, dEta_dau_ap); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_LAp"), qinvLAp_V0, dPhi_V0_ap, dY_V0_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_LAp_dau"), qinvLAp, dPhi_dau_ap, dY_dau_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_LAp_dau"), qinvLAp_dau, dPhi_dau_ap, dY_dau_ap); } // QA3/RawPairDensity: Lambda-antiproton → same LP histogram { @@ -3410,11 +3305,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted AntiLambda-proton pair float qinvALp = 0.0f; { - const float dauPmag = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); + const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); const float pprmag3 = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); - const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); + const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); const float Eppr3 = std::sqrt(pprmag3 * pprmag3 + kMassProton * kMassProton); - qinvALp = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), Edau, primProton.px(), primProton.py(), primProton.pz(), Eppr3); + qinvALp = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primProton.px(), primProton.py(), primProton.pz(), Eppr3); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvALp); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3436,6 +3331,10 @@ struct LambdaProtonBalanceFunction { const float pprmag3_3d = std::sqrt(primProton.px() * primProton.px() + primProton.py() * primProton.py() + primProton.pz() * primProton.pz()); const float Eppr3_3d = std::sqrt(pprmag3_3d * pprmag3_3d + kMassProton * kMassProton); const float qinvALp_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), EalL_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr3_3d); + // q_inv using AntiLambda daughter antiproton (kMassProton hypothesis), only for *_dau histograms + const float dauPmagAL_3d = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); + const float EdauAL_3d = std::sqrt(dauPmagAL_3d * dauPmagAL_3d + kMassProton * kMassProton); + const float qinvALp_dau = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), EdauAL_3d, primProton.px(), primProton.py(), primProton.pz(), Eppr3_3d); // Angular variables w.r.t. AntiLambda daughter antiproton const float dPhi_dauAL_p = RecoDecay::constrainAngle((v0NegDau.phi() - primProton.phi()), -PIHalf3D); const float dEta_dauAL_p = v0NegDau.eta() - primProton.eta(); @@ -3443,10 +3342,10 @@ struct LambdaProtonBalanceFunction { const float dY_dauAL_p = yDauAL - yPrimP3; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALp"), qinvALp_V0, dPhi_AL_p, dEta_AL_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALp_dau"), qinvALp, dPhi_dauAL_p, dEta_dauAL_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALp_dau"), qinvALp_dau, dPhi_dauAL_p, dEta_dauAL_p); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALp"), qinvALp_V0, dPhi_AL_p, dY_AL_p); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALp_dau"), qinvALp, dPhi_dauAL_p, dY_dauAL_p); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALp_dau"), qinvALp_dau, dPhi_dauAL_p, dY_dauAL_p); } // QA3/RawPairDensity: AntiLambda-proton → same LP histogram { @@ -3488,11 +3387,11 @@ struct LambdaProtonBalanceFunction { // QA3/SplitTrackQA: q_inv for every accepted AntiLambda-antiproton pair float qinvALAp = 0.0f; { - const float dauPmag = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); + const float v0pmag = std::sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); const float paprmag2 = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); - const float Edau = std::sqrt(dauPmag * dauPmag + kMassProton * kMassProton); + const float Ev0 = std::sqrt(v0pmag * v0pmag + kMassLambda * kMassLambda); const float Epapr2 = std::sqrt(paprmag2 * paprmag2 + kMassProton * kMassProton); - qinvALAp = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), Edau, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2); + qinvALAp = computeQinv(v0.px(), v0.py(), v0.pz(), Ev0, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2); registryCorrelationQA.fill(HIST("QA3/SplitTrackQA/h1f_qinv_LP_Before_qinvCut"), qinvALAp); } // QA3/SplitTrackQA: q_inv Before and After cut @@ -3514,6 +3413,10 @@ struct LambdaProtonBalanceFunction { const float paprmag2_3d = std::sqrt(primAntiProton.px() * primAntiProton.px() + primAntiProton.py() * primAntiProton.py() + primAntiProton.pz() * primAntiProton.pz()); const float Epapr2_3d = std::sqrt(paprmag2_3d * paprmag2_3d + kMassProton * kMassProton); const float qinvALAp_V0 = computeQinv(v0.px(), v0.py(), v0.pz(), EalL2_3d, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2_3d); + // q_inv using AntiLambda daughter antiproton (kMassProton hypothesis), only for *_dau histograms + const float dauPmagAL2_3d = std::sqrt(v0NegDau.px() * v0NegDau.px() + v0NegDau.py() * v0NegDau.py() + v0NegDau.pz() * v0NegDau.pz()); + const float EdauAL2_3d = std::sqrt(dauPmagAL2_3d * dauPmagAL2_3d + kMassProton * kMassProton); + const float qinvALAp_dau = computeQinv(v0NegDau.px(), v0NegDau.py(), v0NegDau.pz(), EdauAL2_3d, primAntiProton.px(), primAntiProton.py(), primAntiProton.pz(), Epapr2_3d); // Angular variables w.r.t. AntiLambda daughter antiproton const float dPhi_dauAL_ap = RecoDecay::constrainAngle((v0NegDau.phi() - primAntiProton.phi()), -PIHalf3D); const float dEta_dauAL_ap = v0NegDau.eta() - primAntiProton.eta(); @@ -3521,10 +3424,10 @@ struct LambdaProtonBalanceFunction { const float dY_dauAL_ap = yDauAL2 - yPrimAp2; // eta space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALAp"), qinvALAp_V0, dPhi_AL_ap, dEta_AL_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALAp_dau"), qinvALAp, dPhi_dauAL_ap, dEta_dauAL_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/eta/h3f_qinv_dPhi_dEta_ALAp_dau"), qinvALAp_dau, dPhi_dauAL_ap, dEta_dauAL_ap); // y space registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALAp"), qinvALAp_V0, dPhi_AL_ap, dY_AL_ap); - registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALAp_dau"), qinvALAp, dPhi_dauAL_ap, dY_dauAL_ap); + registryCorrelationQA.fill(HIST("QA3/QinvVsAngles/y/h3f_qinv_dPhi_dY_ALAp_dau"), qinvALAp_dau, dPhi_dauAL_ap, dY_dauAL_ap); } // QA3/SplitTrackQA: close-pair block for daughter-overlap diagnosed split tracks { @@ -3869,7 +3772,7 @@ struct LambdaProtonBalanceFunction { LOG(info) << "==============================================="; LOG(info) << ""; } - // ───────────────────────xx────────────────────────────────────────────── + // ───────────────────────────────────────────────────────────────────── }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) From 2149ded55dfd40a4a30307b0d8792777f8ae8931 Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Sat, 31 Oct 2026 00:27:02 +0530 Subject: [PATCH 5/8] Update8 --- .../Tasks/lambdaProtonBalanceFunction.cxx | 563 ++++++++++++++++-- 1 file changed, 508 insertions(+), 55 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index 51b3a29335b..b97f2679952 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -24,6 +24,7 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include #include #include #include @@ -39,13 +40,17 @@ #include #include +#include #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -66,6 +71,9 @@ using MyTracks = soa::Join; +// MC-labelled versions used only by processMC (efficiency maps) +using MyTracksMC = soa::Join; +using MyV0sMC = soa::Join; namespace { @@ -99,6 +107,8 @@ struct LambdaProtonBalanceFunction { // Folder: ProtonVetoQA/ // Contains per-event distributions of N_before, N_after, N_removed, fraction. HistogramRegistry registryProtonVetoQA{"ProtonVetoQA", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + // MC efficiency maps (Gen*/Rec* TH3: x=cent, y=pT, z=y), filled only by processMC. Folder: Efficiency/ + HistogramRegistry registryEff{"Efficiency", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // ════════════════════════════════════════════════════════════════════════ // TaskState — ordinary C++ runtime/implementation state. @@ -178,10 +188,18 @@ struct LambdaProtonBalanceFunction { int mRhoUnrolledBinsY = 0; // mRhoYBins * mRhoPhiBins float mRhoYMin = 0.f; float mRhoYMax = 0.f; + + // 1/efficiency maps (TH3: x=cent, y=pt, z=y); loaded once in init() when cApplyEffCorr is true + TH3* invEffL = nullptr; + TH3* invEffAL = nullptr; + TH3* invEffP = nullptr; + TH3* invEffAP = nullptr; }; TaskState state; + Service ccdb{}; + // ───────────────────────────────────────────────────────────────────── // ── Configurables ───────────────────────────────────────────────────── @@ -196,6 +214,11 @@ struct LambdaProtonBalanceFunction { ConfigurableAxis cCentBins{"cCentBins", {VARIABLE_WIDTH, 0.f, 5.f, 10.f, 20.f, 40.f, 60.f, 80.f}, "Centrality bins (%)"}; Configurable cMinCentrality{"cMinCentrality", 0.0f, "Reject events with centrality below this value (%)"}; Configurable cMaxCentrality{"cMaxCentrality", 80.0f, "Reject events with centrality above this value (%)"}; + Configurable cApplyEffCorr{"cApplyEffCorr", false, "Weight rho1/rho2 by 1/efficiency"}; + Configurable cEffFile{"cEffFile", "", "ROOT file with hInvEff_Lambda, hInvEff_AntiLambda, hInvEff_Proton, hInvEff_AntiProton (TH3: x=cent, y=pt, z=y). Used only if cEffCcdbPath is empty"}; + Configurable cEffCcdbPath{"cEffCcdbPath", "", "CCDB path of a TList holding hInvEff_Lambda, hInvEff_AntiLambda, hInvEff_Proton, hInvEff_AntiProton; if non-empty it is used instead of cEffFile"}; + Configurable cCcdbUrl{"cCcdbUrl", "http://alice-ccdb.cern.ch", "CCDB URL"}; + Configurable cEffCcdbTimestamp{"cEffCcdbTimestamp", 1700000000000, "CCDB timestamp (ms) used to fetch the efficiency maps (must lie inside the object validity)"}; // Track quality cuts Configurable pProtonTPCMinRows{"pProtonTPCMinRows", 70, "Minimum TPC crossed rows"}; @@ -208,7 +231,7 @@ struct LambdaProtonBalanceFunction { Configurable pProtonMaxDCAxy{"pProtonMaxDCAxy", 0.02f, "Max |DCAxy| (cm)"}; // tight cut for cleanest primary-proton sample Configurable pProtonMaxDCAz{"pProtonMaxDCAz", 0.1f, "Max |DCAz| (cm)"}; - Configurable pProtonTPCTOFSwitchP{"pProtonTPCTOFSwitchP", 0.700000238f, "p threshold (GeV/c) above which TOF is used if available"}; + Configurable pProtonTPCTOFSwitchPt{"pProtonTPCTOFSwitchPt", 0.700000238f, "pT threshold (GeV/c) above which TOF is used if available"}; // Configurable cPPMinTofBeta{"cPPMinTofBeta", 0.4f, "Min TOF beta for proton selection (TOF branch only)"}; //BETACUTCommented // Configurable cPPMaxTofBeta{"cPPMaxTofBeta", 0.96f, "Max TOF beta for proton selection (TOF branch only)"}; //BETACUTCommented @@ -240,8 +263,6 @@ struct LambdaProtonBalanceFunction { // ───────────────────────────────────────────────────────────────────── // Proton Kinematic Cuts (from strange9) - Configurable pProtonMinP{"pProtonMinP", 0.5f, "Min p for primary protons (GeV/c)"}; - Configurable pProtonMaxP{"pProtonMaxP", 3.6f, "Max p for primary protons (GeV/c)"}; Configurable pProtonMinPt{"pProtonMinPt", 0.5f, "Min pT for primary protons (GeV/c)"}; Configurable pProtonMaxPt{"pProtonMaxPt", 3.6f, "Max pT for primary protons (GeV/c)"}; @@ -391,25 +412,36 @@ struct LambdaProtonBalanceFunction { } // Fill helper: fills h (if valid) at (a,b) only when both indices are in range. - static void fillIdx(std::shared_ptr const& h, int a, int b) + static void fillIdx(std::shared_ptr const& h, int a, int b, float w = 1.f) { if (h && a >= 0 && b >= 0) { - h->Fill(a + 0.5f, b + 0.5f); + h->Fill(a + 0.5f, b + 0.5f, w); } } + + // Efficiency weight w = 1/eff from the TH3 map (x=cent, y=pt, z=y). 1 when correction is off. + // (TH3* non-const: TH1::FindBin is a non-const method.) + float getEffWeight(TH3* h, float cent, float pt, float y) const + { + if (!cApplyEffCorr.value || !h) { + return 1.f; + } + const float v = h->GetBinContent(h->FindBin(cent, pt, y)); + return v > 0.f ? v : 0.f; // 0 means: particle is dropped (no efficiency info) + } // ───────────────────────────────────────────────────────────────────── // ── Two-region PID selection for (anti)protons ──────────────────────── template bool passesPrimProtonPid(TTrack const& trk) const { - const float pTPC = trk.tpcInnerParam(); // NOTE: pTPC, not trk.p() — matches reference exactly + const float pt = trk.pt(); const float nsPr = trk.tpcNSigmaPr(); if (std::abs(nsPr) >= pProtonTPCNsigma.value) { return false; } - if (pTPC < pProtonTPCTOFSwitchP.value) { + if (pt < pProtonTPCTOFSwitchPt.value) { return true; } if (!trk.hasTOF()) { @@ -420,11 +452,11 @@ struct LambdaProtonBalanceFunction { // Bitmask of contaminant hypotheses that REJECT the track (bit0 = pi, bit1 = K, bit2 = e). // A hypothesis rejects only if the track is inside its veto window AND closer to it than to the proton. - // Detector: TOF at/above the TPC/TOF switch momentum when TOF is available, TPC otherwise. + // Detector: TOF at/above the TPC/TOF switch pT when TOF is available, TPC otherwise. template int contaminantVetoMask(TTrack const& trk, bool& usedTOF) const { - usedTOF = cVetoUseTOF.value && trk.hasTOF() && trk.tpcInnerParam() >= pProtonTPCTOFSwitchP.value; + usedTOF = cVetoUseTOF.value && trk.hasTOF() && trk.pt() >= pProtonTPCTOFSwitchPt.value; const float nsP = std::abs(usedTOF ? trk.tofNSigmaPr() : trk.tpcNSigmaPr()); const float nsPi = std::abs(usedTOF ? trk.tofNSigmaPi() : trk.tpcNSigmaPi()); const float nsK = std::abs(usedTOF ? trk.tofNSigmaKa() : trk.tpcNSigmaKa()); @@ -481,7 +513,7 @@ struct LambdaProtonBalanceFunction { enum class ProtonQAStage : int { RawAfterTrackSel = 0, ///< after track-quality selection (TrackSelection table), before DCA cuts and PID TpcPid = 1, ///< after DCA + TPC PID cut passes (all momenta) - TpcTofPid = 2, ///< after DCA + full PID: TPC everywhere, plus TOF required only above pProtonTPCTOFSwitchP + TpcTofPid = 2, ///< after DCA + full PID: TPC everywhere, plus TOF required only above pProtonTPCTOFSwitchPt FinalSelected = 3 ///< entered selectedPrimProtons / selectedPrimAntiProtons }; @@ -1242,6 +1274,19 @@ struct LambdaProtonBalanceFunction { // ── Other / event-level histograms ─────────────────────────────────── registryOther.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); registryOther.add("hFT0MPercentile", ("Centrality percentile (" + centLabel + ")").c_str(), {HistType::kTH1F, {multAxis}}); + // ── MC efficiency maps (processMC): x = centrality (cCentBins), y = pT, z = y (same range/bins as rho1) ── + { + const AxisSpec axCent(cCentBins, "centrality (%)"); + const AxisSpec axPt{60, 0.0, 6.0, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec axY{cRhoYBins.value, cRhoYMin.value, cRhoYMax.value, "y"}; + for (const char* name : {"GenLambda", "GenAntiLambda", "GenProton", "GenAntiProton", + "RecLambda", "RecAntiLambda", "RecProton", "RecAntiProton"}) { + registryEff.add(name, name, {HistType::kTH3F, {axCent, axPt, axY}}); + } + } + registryOther.add("hEffWeightProton", "Efficiency weight 1/#epsilon, protons", {HistType::kTH1F, {{200, 0.0f, 20.0f}}}); + registryOther.add("hEffWeightLambda", "Efficiency weight 1/#epsilon, #Lambda", {HistType::kTH1F, {{200, 0.0f, 20.0f}}}); + registryOther.add("hEffWeightZeroCount", "Particles with efficiency weight 0 (1=p, 2=#bar{p}, 3=#Lambda, 4=#bar{#Lambda})", {HistType::kTH1F, {{4, 0.5f, 4.5f}}}); registryOther.add("hNSelectedPrimProtons", "Number of selected primary protons per event", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); registryOther.add("hNSelectedPrimAntiProtons", "Number of selected primary antiprotons per event", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); registryOther.add("hNSelLambda", "Number of selected Lambda candidates per event", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); @@ -2055,6 +2100,92 @@ struct LambdaProtonBalanceFunction { addY(S.ALAL_y, "h2_rho2_ALAL_y_AllPt", "#rho_{2}(#bar{#Lambda},#bar{#Lambda}) (y,#varphi)"); } } + + // ── Efficiency correction: load 1/eff maps once ────────────────────── + if (cApplyEffCorr.value) { + if (!cEffCcdbPath.value.empty()) { + // ── load from CCDB (TList of TH3) ── + ccdb->setURL(cCcdbUrl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + TList* effList = ccdb->getForTimeStamp(cEffCcdbPath.value, cEffCcdbTimestamp.value); + if (!effList) { + LOGF(fatal, "Cannot get efficiency TList from CCDB path %s (timestamp %" PRId64 ")", cEffCcdbPath.value.c_str(), static_cast(cEffCcdbTimestamp.value)); + } + auto loadMap = [&](const char* name) -> TH3* { + auto* obj = effList->FindObject(name); + if (!obj) { + LOGF(fatal, "Missing efficiency map %s in CCDB object", name); + } + TH3* h = dynamic_cast(obj->Clone()); + if (!h) { + LOGF(fatal, "Object %s in CCDB could not be cast to TH3*", name); + } + h->SetDirectory(nullptr); + return h; + }; + state.invEffL = loadMap("hInvEff_Lambda"); + state.invEffAL = loadMap("hInvEff_AntiLambda"); + state.invEffP = loadMap("hInvEff_Proton"); + state.invEffAP = loadMap("hInvEff_AntiProton"); + } else { + // ── load from a ROOT file (fallback / local tests) ── + TFile* fEff = TFile::Open(cEffFile.value.c_str(), "READ"); + if (!fEff || fEff->IsZombie()) { + LOGF(fatal, "Cannot open efficiency file %s", cEffFile.value.c_str()); + } + auto loadMap = [&](const char* name) -> TH3* { + TH3* h = dynamic_cast(fEff->Get(name)); + if (!h) { + LOGF(fatal, "Missing efficiency map %s", name); + } + h->SetDirectory(nullptr); + return h; + }; + state.invEffL = loadMap("hInvEff_Lambda"); + state.invEffAL = loadMap("hInvEff_AntiLambda"); + state.invEffP = loadMap("hInvEff_Proton"); + state.invEffAP = loadMap("hInvEff_AntiProton"); + fEff->Close(); + } + + // Sumw2 for all weighted fills (rho1, and every rho2 channel: Lp family, pp family, LL family) + registryRho.get(HIST("h2_rho1_Proton_y"))->Sumw2(); + registryRho.get(HIST("h2_rho1_AntiProton_y"))->Sumw2(); + registryRho.get(HIST("h2_rho1_Lambda_y"))->Sumw2(); + registryRho.get(HIST("h2_rho1_AntiLambda_y"))->Sumw2(); + state.hRho2_Lp_y_AllPt->Sumw2(); + state.hRho2_LAp_y_AllPt->Sumw2(); + state.hRho2_ALp_y_AllPt->Sumw2(); + state.hRho2_ALAp_y_AllPt->Sumw2(); + state.hRho2_pp_y_AllPt->Sumw2(); + state.hRho2_pAp_y_AllPt->Sumw2(); + state.hRho2_App_y_AllPt->Sumw2(); + state.hRho2_ApAp_y_AllPt->Sumw2(); + state.hRho2_LL_y_AllPt->Sumw2(); + state.hRho2_LAL_y_AllPt->Sumw2(); + state.hRho2_ALL_y_AllPt->Sumw2(); + state.hRho2_ALAL_y_AllPt->Sumw2(); + for (auto& S : state.centSets) { + S.rho1_Proton_y->Sumw2(); + S.rho1_AntiProton_y->Sumw2(); + S.rho1_Lambda_y->Sumw2(); + S.rho1_AntiLambda_y->Sumw2(); + S.Lp_y->Sumw2(); + S.LAp_y->Sumw2(); + S.ALp_y->Sumw2(); + S.ALAp_y->Sumw2(); + S.pp_y->Sumw2(); + S.pAp_y->Sumw2(); + S.App_y->Sumw2(); + S.ApAp_y->Sumw2(); + S.LL_y->Sumw2(); + S.LAL_y->Sumw2(); + S.ALL_y->Sumw2(); + S.ALAL_y->Sumw2(); + } + } } Filter eventFilter = (o2::aod::evsel::sel8 == true); @@ -2080,9 +2211,9 @@ struct LambdaProtonBalanceFunction { } // ───────────────────────────────────────────────────────────────────── - void process(soa::Filtered>::iterator const& collision, - aod::V0Datas const& V0s, - MyTracks const& tracks) + void processData(soa::Filtered>::iterator const& collision, + aod::V0Datas const& V0s, + MyTracks const& tracks) { // ── Ordered-pair convention ──────────────────────────────────────────── // pp : trigger=proton1, assoc=proton2 (self-pairs rejected) @@ -2098,7 +2229,7 @@ struct LambdaProtonBalanceFunction { // Every channel fills y-space only (unrolledIndexY). // ───────────────────────────────────────────────────────────────────── - // ── Event cutflow bin 1 — enters process (after sel8 + posZ filters) ── + // ── Event cutflow bin 1 — enters processData (after sel8 + posZ filters) ── registryOther.fill(HIST("hEventCutflow"), 1.0f); if (collision.numContrib() < 1) { @@ -2553,9 +2684,14 @@ struct LambdaProtonBalanceFunction { fillDaughterQA(DaughterQAStage::Final, dauPos); fillDaughterQA(DaughterQAStage::Final, dauNeg); } - registryRho.fill(HIST("h2_rho1_Lambda_y"), v0.rapidity(1), v0.phi()); + const float wL = getEffWeight(state.invEffL, cent, v0.pt(), v0.rapidity(1)); + registryRho.fill(HIST("h2_rho1_Lambda_y"), v0.rapidity(1), v0.phi(), wL); if (cs) { - cs->rho1_Lambda_y->Fill(v0.rapidity(1), v0.phi()); + cs->rho1_Lambda_y->Fill(v0.rapidity(1), v0.phi(), wL); + } + registryOther.fill(HIST("hEffWeightLambda"), wL); + if (wL == 0.f) { + registryOther.fill(HIST("hEffWeightZeroCount"), 3.f); } registryOther.fill(HIST("hPtSelLambda"), v0.pt()); state.hPtSelLambda_AllPt->Fill(v0.pt()); @@ -2571,9 +2707,13 @@ struct LambdaProtonBalanceFunction { fillDaughterQA(DaughterQAStage::Final, dauNeg); fillDaughterQA(DaughterQAStage::Final, dauPos); } - registryRho.fill(HIST("h2_rho1_AntiLambda_y"), v0.rapidity(2), v0.phi()); + const float wAL = getEffWeight(state.invEffAL, cent, v0.pt(), v0.rapidity(2)); + registryRho.fill(HIST("h2_rho1_AntiLambda_y"), v0.rapidity(2), v0.phi(), wAL); if (cs) { - cs->rho1_AntiLambda_y->Fill(v0.rapidity(2), v0.phi()); + cs->rho1_AntiLambda_y->Fill(v0.rapidity(2), v0.phi(), wAL); + } + if (wAL == 0.f) { + registryOther.fill(HIST("hEffWeightZeroCount"), 4.f); } registryOther.fill(HIST("hPtSelAntiLambda"), v0.pt()); state.hPtSelAntiLambda_AllPt->Fill(v0.pt()); @@ -2639,11 +2779,7 @@ struct LambdaProtonBalanceFunction { fillCutFlow(8.0f, trk); // ───────────────────────────────────────────────────────────────── - // ── p_TPC and pT acceptance cuts ───────────────────────────────────────────── - const float pTPC = trk.tpcInnerParam(); - if (pTPC < pProtonMinP.value || pTPC > pProtonMaxP.value) { - continue; - } + // ── pT acceptance cut ───────────────────────────────────────────── if (trk.pt() < pProtonMinPt.value || trk.pt() > pProtonMaxPt.value) { continue; } @@ -2808,8 +2944,8 @@ struct LambdaProtonBalanceFunction { fillProtonDetectorQuality(ProtonQAStage::FinalSelected, trk); fillProtonTpcQA(ProtonQAStage::FinalSelected, trk); // TOF QA only when track was accepted through the TPC+TOF branch: - // p > PProtonTPC_TOFSwitchP guarantees hasTOF() and nSigmaTOF passed (beta window cut removed). //BETACUTCommented - if (pTPC >= pProtonTPCTOFSwitchP.value) { + // pt > pProtonTPCTOFSwitchPt guarantees hasTOF() and nSigmaTOF passed (beta window cut removed). //BETACUTCommented + if (trk.pt() >= pProtonTPCTOFSwitchPt.value) { fillProtonTofQA(ProtonQAStage::FinalSelected, trk); } @@ -2821,8 +2957,8 @@ struct LambdaProtonBalanceFunction { fillProtonDetectorQuality(ProtonQAStage::FinalSelected, trk); fillProtonTpcQA(ProtonQAStage::FinalSelected, trk); // TOF QA only when track was accepted through the TPC+TOF branch: - // p > pProtonTPCTOFSwitchP guarantees hasTOF() and nSigmaTOF passed (beta window cut removed). //BETACUTCommented - if (pTPC >= pProtonTPCTOFSwitchP.value) { + // pt > pProtonTPCTOFSwitchPt guarantees hasTOF() and nSigmaTOF passed (beta window cut removed). //BETACUTCommented + if (trk.pt() >= pProtonTPCTOFSwitchPt.value) { fillProtonTofQA(ProtonQAStage::FinalSelected, trk); } @@ -2870,16 +3006,25 @@ struct LambdaProtonBalanceFunction { // ── Single-particle density for protons (y) ────────────────── for (auto const& primProton : selectedPrimProtons) { const float yp = protonRapidity(primProton); - registryRho.fill(HIST("h2_rho1_Proton_y"), yp, primProton.phi()); + const float wP = getEffWeight(state.invEffP, cent, primProton.pt(), yp); + registryRho.fill(HIST("h2_rho1_Proton_y"), yp, primProton.phi(), wP); if (cs) { - cs->rho1_Proton_y->Fill(yp, primProton.phi()); + cs->rho1_Proton_y->Fill(yp, primProton.phi(), wP); + } + registryOther.fill(HIST("hEffWeightProton"), wP); + if (wP == 0.f) { + registryOther.fill(HIST("hEffWeightZeroCount"), 1.f); } } for (auto const& primAntiProton : selectedPrimAntiProtons) { const float yap = protonRapidity(primAntiProton); - registryRho.fill(HIST("h2_rho1_AntiProton_y"), yap, primAntiProton.phi()); + const float wAP = getEffWeight(state.invEffAP, cent, primAntiProton.pt(), yap); + registryRho.fill(HIST("h2_rho1_AntiProton_y"), yap, primAntiProton.phi(), wAP); if (cs) { - cs->rho1_AntiProton_y->Fill(yap, primAntiProton.phi()); + cs->rho1_AntiProton_y->Fill(yap, primAntiProton.phi(), wAP); + } + if (wAP == 0.f) { + registryOther.fill(HIST("hEffWeightZeroCount"), 2.f); } } // ───────────────────────────────────────────────────────────────────── @@ -2963,11 +3108,12 @@ struct LambdaProtonBalanceFunction { const int idxY1 = unrolledIndexY(y1_pp, p1.phi()); const int idxY2 = unrolledIndexY(y2_pp, p2.phi()); // Physics pair correlations (rho2): q_inv cut applied (pairs with q_inv <= kQinvCut are rejected above) + const float wPair = getEffWeight(state.invEffP, cent, p1.pt(), y1_pp) * getEffWeight(state.invEffP, cent, p2.pt(), y2_pp); if (idxY1 >= 0 && idxY2 >= 0) { - state.hRho2_pp_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f); + state.hRho2_pp_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f, wPair); } if (cs) { - fillIdx(cs->pp_y, idxY1, idxY2); + fillIdx(cs->pp_y, idxY1, idxY2, wPair); } } } @@ -2981,11 +3127,12 @@ struct LambdaProtonBalanceFunction { if (failsQinvCut(qinvPAp)) { continue; } + const float wPair = getEffWeight(state.invEffP, cent, a.pt, a.y) * getEffWeight(state.invEffAP, cent, b.pt, b.y); if (a.idxY >= 0 && b.idxY >= 0) { - state.hRho2_pAp_y_AllPt->Fill(a.idxY + 0.5f, b.idxY + 0.5f); + state.hRho2_pAp_y_AllPt->Fill(a.idxY + 0.5f, b.idxY + 0.5f, wPair); } if (cs) { - fillIdx(cs->pAp_y, a.idxY, b.idxY); + fillIdx(cs->pAp_y, a.idxY, b.idxY, wPair); } } } @@ -2999,11 +3146,12 @@ struct LambdaProtonBalanceFunction { if (failsQinvCut(qinvApp)) { continue; } + const float wPair = getEffWeight(state.invEffAP, cent, a.pt, a.y) * getEffWeight(state.invEffP, cent, b.pt, b.y); if (a.idxY >= 0 && b.idxY >= 0) { - state.hRho2_App_y_AllPt->Fill(a.idxY + 0.5f, b.idxY + 0.5f); + state.hRho2_App_y_AllPt->Fill(a.idxY + 0.5f, b.idxY + 0.5f, wPair); } if (cs) { - fillIdx(cs->App_y, a.idxY, b.idxY); + fillIdx(cs->App_y, a.idxY, b.idxY, wPair); } } } @@ -3020,11 +3168,12 @@ struct LambdaProtonBalanceFunction { if (failsQinvCut(qinvApAp)) { continue; } + const float wPair = getEffWeight(state.invEffAP, cent, a.pt, a.y) * getEffWeight(state.invEffAP, cent, b.pt, b.y); if (a.idxY >= 0 && b.idxY >= 0) { - state.hRho2_ApAp_y_AllPt->Fill(a.idxY + 0.5f, b.idxY + 0.5f); + state.hRho2_ApAp_y_AllPt->Fill(a.idxY + 0.5f, b.idxY + 0.5f, wPair); } if (cs) { - fillIdx(cs->ApAp_y, a.idxY, b.idxY); + fillIdx(cs->ApAp_y, a.idxY, b.idxY, wPair); } } } @@ -3136,11 +3285,12 @@ struct LambdaProtonBalanceFunction { if (idxYL >= 0 && idxYP >= 0 && bin >= 0) { state.hPtPrimProton_Lambda[bin]->Fill(primProton.pt()); } + const float wPair = getEffWeight(state.invEffL, cent, v0.pt(), yL) * getEffWeight(state.invEffP, cent, primProton.pt(), yP); if (idxYL >= 0 && idxYP >= 0) { - state.hRho2_Lp_y_AllPt->Fill(idxYL + 0.5f, idxYP + 0.5f); + state.hRho2_Lp_y_AllPt->Fill(idxYL + 0.5f, idxYP + 0.5f, wPair); } if (cs) { - fillIdx(cs->Lp_y, idxYL, idxYP); + fillIdx(cs->Lp_y, idxYL, idxYP, wPair); } ++nPairs_Lambda_PrimProton; } @@ -3218,11 +3368,12 @@ struct LambdaProtonBalanceFunction { if (idxYL2 >= 0 && idxYAp >= 0 && bin >= 0) { state.hPtPrimAntiProton_Lambda[bin]->Fill(primAntiProton.pt()); } + const float wPair = getEffWeight(state.invEffL, cent, v0.pt(), yL2) * getEffWeight(state.invEffAP, cent, primAntiProton.pt(), yAp); if (idxYL2 >= 0 && idxYAp >= 0) { - state.hRho2_LAp_y_AllPt->Fill(idxYL2 + 0.5f, idxYAp + 0.5f); + state.hRho2_LAp_y_AllPt->Fill(idxYL2 + 0.5f, idxYAp + 0.5f, wPair); } if (cs) { - fillIdx(cs->LAp_y, idxYL2, idxYAp); + fillIdx(cs->LAp_y, idxYL2, idxYAp, wPair); } ++nPairs_Lambda_PrimAntiProton; } @@ -3372,11 +3523,12 @@ struct LambdaProtonBalanceFunction { if (idxYAL >= 0 && idxYP2 >= 0 && bin >= 0) { state.hPtPrimProton_AntiLambda[bin]->Fill(primProton.pt()); } + const float wPair = getEffWeight(state.invEffAL, cent, v0.pt(), yAL) * getEffWeight(state.invEffP, cent, primProton.pt(), yP2); if (idxYAL >= 0 && idxYP2 >= 0) { - state.hRho2_ALp_y_AllPt->Fill(idxYAL + 0.5f, idxYP2 + 0.5f); + state.hRho2_ALp_y_AllPt->Fill(idxYAL + 0.5f, idxYP2 + 0.5f, wPair); } if (cs) { - fillIdx(cs->ALp_y, idxYAL, idxYP2); + fillIdx(cs->ALp_y, idxYAL, idxYP2, wPair); } ++nPairs_AntiLambda_PrimProton; } @@ -3461,11 +3613,12 @@ struct LambdaProtonBalanceFunction { if (idxYAL2 >= 0 && idxYAp2 >= 0 && bin >= 0) { state.hPtPrimAntiProton_AntiLambda[bin]->Fill(primAntiProton.pt()); } + const float wPair = getEffWeight(state.invEffAL, cent, v0.pt(), yAL2) * getEffWeight(state.invEffAP, cent, primAntiProton.pt(), yAp2); if (idxYAL2 >= 0 && idxYAp2 >= 0) { - state.hRho2_ALAp_y_AllPt->Fill(idxYAL2 + 0.5f, idxYAp2 + 0.5f); + state.hRho2_ALAp_y_AllPt->Fill(idxYAL2 + 0.5f, idxYAp2 + 0.5f, wPair); } if (cs) { - fillIdx(cs->ALAp_y, idxYAL2, idxYAp2); + fillIdx(cs->ALAp_y, idxYAL2, idxYAp2, wPair); } ++nPairs_AntiLambda_PrimAntiProton; } @@ -3575,11 +3728,12 @@ struct LambdaProtonBalanceFunction { const int idxY1 = unrolledIndexY(yv1L, v1.phi()); const int idxY2 = unrolledIndexY(v2.rapidity(1), v2.phi()); // Physics pair correlations (rho2): q_inv cut applied (pairs with q_inv <= kQinvCut are rejected above) + const float wPair = getEffWeight(state.invEffL, cent, v1.pt(), yv1L) * getEffWeight(state.invEffL, cent, v2.pt(), v2.rapidity(1)); if (idxY1 >= 0 && idxY2 >= 0) { - state.hRho2_LL_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f); + state.hRho2_LL_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f, wPair); } if (cs) { - fillIdx(cs->LL_y, idxY1, idxY2); + fillIdx(cs->LL_y, idxY1, idxY2, wPair); } } } @@ -3625,11 +3779,12 @@ struct LambdaProtonBalanceFunction { const int idxY1 = unrolledIndexY(yv1LAL, v1.phi()); const int idxY2 = unrolledIndexY(v2.rapidity(2), v2.phi()); // Physics pair correlations (rho2): q_inv cut applied (pairs with q_inv <= kQinvCut are rejected above) + const float wPair = getEffWeight(state.invEffL, cent, v1.pt(), yv1LAL) * getEffWeight(state.invEffAL, cent, v2.pt(), v2.rapidity(2)); if (idxY1 >= 0 && idxY2 >= 0) { - state.hRho2_LAL_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f); + state.hRho2_LAL_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f, wPair); } if (cs) { - fillIdx(cs->LAL_y, idxY1, idxY2); + fillIdx(cs->LAL_y, idxY1, idxY2, wPair); } } } @@ -3675,11 +3830,12 @@ struct LambdaProtonBalanceFunction { const int idxY1 = unrolledIndexY(yv1ALL, v1.phi()); const int idxY2 = unrolledIndexY(v2.rapidity(1), v2.phi()); // Physics pair correlations (rho2): q_inv cut applied (pairs with q_inv <= kQinvCut are rejected above) + const float wPair = getEffWeight(state.invEffAL, cent, v1.pt(), yv1ALL) * getEffWeight(state.invEffL, cent, v2.pt(), v2.rapidity(1)); if (idxY1 >= 0 && idxY2 >= 0) { - state.hRho2_ALL_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f); + state.hRho2_ALL_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f, wPair); } if (cs) { - fillIdx(cs->ALL_y, idxY1, idxY2); + fillIdx(cs->ALL_y, idxY1, idxY2, wPair); } } } @@ -3728,11 +3884,12 @@ struct LambdaProtonBalanceFunction { const int idxY1 = unrolledIndexY(yv1ALAL, v1.phi()); const int idxY2 = unrolledIndexY(v2.rapidity(2), v2.phi()); // Physics pair correlations (rho2): q_inv cut applied (pairs with q_inv <= kQinvCut are rejected above) + const float wPair = getEffWeight(state.invEffAL, cent, v1.pt(), yv1ALAL) * getEffWeight(state.invEffAL, cent, v2.pt(), v2.rapidity(2)); if (idxY1 >= 0 && idxY2 >= 0) { - state.hRho2_ALAL_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f); + state.hRho2_ALAL_y_AllPt->Fill(idxY1 + 0.5f, idxY2 + 0.5f, wPair); } if (cs) { - fillIdx(cs->ALAL_y, idxY1, idxY2); + fillIdx(cs->ALAL_y, idxY1, idxY2, wPair); } } } @@ -3745,6 +3902,302 @@ struct LambdaProtonBalanceFunction { registryOther.fill(HIST("hNPairs_AntiLambda_PrimProton"), static_cast(nPairs_AntiLambda_PrimProton)); registryOther.fill(HIST("hNPairs_AntiLambda_PrimAntiProton"), static_cast(nPairs_AntiLambda_PrimAntiProton)); } + PROCESS_SWITCH(LambdaProtonBalanceFunction, processData, "Process for Data", true); + + // ══════════════════════════════════════════════════════════════════════════ + // MC efficiency maps: Gen* from MC particles, Rec* from the reconstructed selection. + // Gen* use MC-truth pT and y (proton mass for p/pbar, Lambda mass for Lambda/AntiLambda). + // Rec* use RECONSTRUCTED pT and y, i.e. the same variables getEffWeight() queries in processData(). + // The loop is driven by MC collisions (exactly one reconstructed collision required) to avoid + // split-vertex double counting of generated particles. + // ══════════════════════════════════════════════════════════════════════════ + Preslice v0sPerCollision = aod::v0data::collisionId; + Preslice tracksPerCollision = aod::track::collisionId; + + template + static float mcRapidity(TMc const& mc, float mass) + { + return RecoDecay::y(std::array{mc.px(), mc.py(), mc.pz()}, mass); + } + // Generator-level acceptance = same pT range and |y| cut as the reco selection of the species. + bool inLambdaAcc(float pt, float y) const + { + return pt > lambdaV0MinPt.value && pt < lambdaV0MaxPt.value && std::abs(y) < lambdaV0MaxY.value; + } + bool inProtonAcc(float pt, float y) const + { + return pt > pProtonMinPt.value && pt < pProtonMaxPt.value && std::abs(y) < pProtonMaxY.value; + } + + void processMC(aod::McCollisions::iterator const& mcCollision, + soa::SmallGroups> const& collisions, + MyV0sMC const& allV0s, + MyTracksMC const& allTracks, + aod::McParticles const& mcParticles) + { + // ── 1) Event association + selection (soa::Filtered does not apply to SmallGroups) ── + // Exactly one reconstructed collision per MC collision: removes split-vertex double counting. + if (collisions.size() != 1) { + return; + } + auto collision = collisions.begin(); + if (!collision.has_mcCollision() || collision.mcCollisionId() != mcCollision.globalIndex()) { + return; + } + // Same event selection as the Filters of processData(): sel8 + |posZ| cut + if (!collision.sel8() || std::abs(collision.posZ()) >= cPPandV0ZVertexCut.value) { + return; + } + // Slice V0s and tracks to this reconstructed collision + auto V0s = allV0s.sliceBy(v0sPerCollision, collision.globalIndex()); + auto tracks = allTracks.sliceBy(tracksPerCollision, collision.globalIndex()); + + if (collision.numContrib() < 1) { + return; + } + const float cent = getCentrality(collision); // FT0C or FT0M according to cUseFT0C + if (cent < cMinCentrality.value || cent >= cMaxCentrality.value) { + return; + } + // INEL > 0 (same as processData()): at least one charged track in |eta| < 0.8 + { + int nTracksINEL = 0; + for (auto const& trk : tracks) { + if (std::abs(trk.eta()) < 0.8f) { + ++nTracksINEL; + } + } + if (nTracksINEL < 1) { + return; + } + } + + // ── 2) GENERATED: physical primaries of this MC collision (mcParticles is auto-sliced to mcCollision; + // NO V0-daughter veto at generator level) ── + for (auto const& mc : mcParticles) { + if (!mc.isPhysicalPrimary()) { + continue; + } + const int pdg = mc.pdgCode(); + if (pdg == 3122 || pdg == -3122) { + if (!mc.has_daughters()) { + continue; + } + const float pt = mc.pt(); + const float y = mcRapidity(mc, kMassLambda); + if (!inLambdaAcc(pt, y)) { + continue; + } + if (pdg == 3122) { + registryEff.fill(HIST("GenLambda"), cent, pt, y); + } else { + registryEff.fill(HIST("GenAntiLambda"), cent, pt, y); + } + } else if (pdg == 2212 || pdg == -2212) { + const float pt = mc.pt(); + const float y = mcRapidity(mc, kMassProton); + if (!inProtonAcc(pt, y)) { + continue; + } + if (pdg == 2212) { + registryEff.fill(HIST("GenProton"), cent, pt, y); + } else { + registryEff.fill(HIST("GenAntiProton"), cent, pt, y); + } + } + } + + // ══════════════════════════════════════════════════════════════════════ + // BLOCK COPIED FROM processData() — V0 (Lambda/AntiLambda) selection. + // The selection is embedded in processData(), so it is duplicated here with all QA fills removed. + // KEEP IN SYNC with processData() (Step 2 V0 loop + shared-daughter cleaning). + // ══════════════════════════════════════════════════════════════════════ + constexpr float mLambdaPDG = o2::constants::physics::MassLambda; + constexpr float mK0PDG = o2::constants::physics::MassK0Short; + std::unordered_set v0DaughterTrackIds; + std::vector selectedLambdas; + std::vector selectedAntiLambdas; + + for (const auto& v0 : V0s) { + const auto& v0PosDau = v0.posTrack_as(); + const auto& v0NegDau = v0.negTrack_as(); + + if (v0.v0Type() != cV0TypeSelection.value) { + continue; + } + if (v0PosDau.pt() <= cV0DauMinPt.value || v0NegDau.pt() <= cV0DauMinPt.value || + std::abs(v0PosDau.eta()) >= cV0DauMaxEta.value || std::abs(v0NegDau.eta()) >= cV0DauMaxEta.value || + v0PosDau.tpcNClsCrossedRows() <= cV0DauMinTpcCrossedRows.value || + v0NegDau.tpcNClsCrossedRows() <= cV0DauMinTpcCrossedRows.value) { + continue; + } + const bool v0DauPID_AsLambda = + (std::abs(v0PosDau.tpcNSigmaPr()) < lambdaV0DaughterProtonTPCNsigma.value) && + (std::abs(v0NegDau.tpcNSigmaPi()) < lambdaV0DaughterPionTPCNsigma.value); + const bool v0DauPID_AsAntiLambda = + (std::abs(v0PosDau.tpcNSigmaPi()) < lambdaV0DaughterPionTPCNsigma.value) && + (std::abs(v0NegDau.tpcNSigmaPr()) < lambdaV0DaughterProtonTPCNsigma.value); + if (v0DauPID_AsLambda == v0DauPID_AsAntiLambda) { + continue; + } + if (v0DauPID_AsLambda && std::abs(v0.rapidity(1)) > lambdaV0MaxY.value) { + continue; + } + if (v0DauPID_AsAntiLambda && std::abs(v0.rapidity(2)) > lambdaV0MaxY.value) { + continue; + } + if (v0.pt() < lambdaV0MinPt.value || v0.pt() > lambdaV0MaxPt.value) { + continue; + } + const float dcaProton = v0DauPID_AsLambda ? std::abs(v0.dcapostopv()) : std::abs(v0.dcanegtopv()); + const float dcaPion = v0DauPID_AsLambda ? std::abs(v0.dcanegtopv()) : std::abs(v0.dcapostopv()); + const float ctau = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * mLambdaPDG; + if (!passTopoCuts(v0)) { + continue; + } + if (dcaProton < lambdaV0DaughterProtonMinDCAToPV.value || + dcaPion < lambdaV0DaughterPionMinDCAToPV.value) { + continue; + } + if (ctau > lambdaV0MaxCTau.value) { + continue; + } + if (std::abs(v0.mK0Short() - mK0PDG) <= lambdaV0KShortRejectMassWindow.value) { + continue; + } + const bool selLambda = v0DauPID_AsLambda && (std::abs(v0.mLambda() - mLambdaPDG) < lambdaV0MassWindow.value); + const bool selAntiLambda = v0DauPID_AsAntiLambda && (std::abs(v0.mAntiLambda() - mLambdaPDG) < lambdaV0MassWindow.value); + if (selLambda) { + selectedLambdas.push_back(v0); + v0DaughterTrackIds.insert(v0.posTrackId()); + v0DaughterTrackIds.insert(v0.negTrackId()); + } + if (selAntiLambda) { + selectedAntiLambdas.push_back(v0); + v0DaughterTrackIds.insert(v0.posTrackId()); + v0DaughterTrackIds.insert(v0.negTrackId()); + } + } + // Shared-daughter cleaning (same as processData()) + std::unordered_map posIdCount; + std::unordered_map negIdCount; + for (const auto& v : selectedLambdas) { + ++posIdCount[v.posTrackId()]; + ++negIdCount[v.negTrackId()]; + } + for (const auto& v : selectedAntiLambdas) { + ++posIdCount[v.posTrackId()]; + ++negIdCount[v.negTrackId()]; + } + std::vector cleanLambdas; + std::vector cleanAntiLambdas; + for (const auto& v : selectedLambdas) { + if (posIdCount[v.posTrackId()] == 1 && negIdCount[v.negTrackId()] == 1) { + cleanLambdas.push_back(v); + } + } + for (const auto& v : selectedAntiLambdas) { + if (posIdCount[v.posTrackId()] == 1 && negIdCount[v.negTrackId()] == 1) { + cleanAntiLambdas.push_back(v); + } + } + // ══════════════ END OF BLOCK COPIED FROM processData() (V0) ══════════════ + + // ── 4) RECONSTRUCTED Lambda / AntiLambda: true primary (anti)Lambda, filled in RECONSTRUCTED (pT, y) ── + for (const auto& v0 : cleanLambdas) { + const auto& v0PosDau = v0.posTrack_as(); + const auto& v0NegDau = v0.negTrack_as(); + if (!v0.has_mcParticle() || !v0PosDau.has_mcParticle() || !v0NegDau.has_mcParticle()) { + continue; + } + const auto mc = v0.mcParticle_as(); + if (!mc.isPhysicalPrimary() || mc.pdgCode() != 3122) { + continue; + } + registryEff.fill(HIST("RecLambda"), cent, v0.pt(), v0.rapidity(1)); + } + for (const auto& v0 : cleanAntiLambdas) { + const auto& v0PosDau = v0.posTrack_as(); + const auto& v0NegDau = v0.negTrack_as(); + if (!v0.has_mcParticle() || !v0PosDau.has_mcParticle() || !v0NegDau.has_mcParticle()) { + continue; + } + const auto mc = v0.mcParticle_as(); + if (!mc.isPhysicalPrimary() || mc.pdgCode() != -3122) { + continue; + } + registryEff.fill(HIST("RecAntiLambda"), cent, v0.pt(), v0.rapidity(2)); + } + + // ══════════════════════════════════════════════════════════════════════ + // BLOCK COPIED FROM processData() — primary (anti)proton selection (track loop, QA fills removed). + // Reuses passesPrimProtonPid() and passesContaminantVeto(); the remaining cuts are embedded + // in processData() and duplicated here. KEEP IN SYNC with processData(). + // ══════════════════════════════════════════════════════════════════════ + for (auto const& trk : tracks) { + if (!trk.hasTPC()) { + continue; + } + if (trk.tpcNClsCrossedRows() < pProtonTPCMinRows.value) { + continue; + } + if (trk.tpcCrossedRowsOverFindableCls() < pProtonTPCMinRowsOverFindable.value) { + continue; + } + if (trk.tpcChi2NCl() > pProtonTPCMaxChi2PerCluster.value) { + continue; + } + if (trk.itsNCls() < pProtonITSMinClusters.value) { + continue; + } + if (trk.itsChi2NCl() > pProtonITSMaxChi2PerCluster.value) { + continue; + } + if (trk.tpcSignal() < cPPMinTpcSignal.value) { + continue; + } + if (trk.pt() < pProtonMinPt.value || trk.pt() > pProtonMaxPt.value) { + continue; + } + if (std::abs(protonRapidity(trk)) > pProtonMaxY.value) { + continue; + } + if (!((std::abs(trk.dcaXY()) < pProtonMaxDCAxy.value) && (std::abs(trk.dcaZ()) < pProtonMaxDCAz.value))) { + continue; + } + if (!passesPrimProtonPid(trk)) { + continue; + } + if (!passesContaminantVeto(trk)) { + continue; + } + // V0-daughter veto (same set as processData(): built from V0s selected before shared-daughter cleaning) + if (v0DaughterTrackIds.contains(trk.globalIndex())) { + continue; + } + // ══════════════ END OF BLOCK COPIED FROM processData() (protons) ══════════════ + + // ── 3) RECONSTRUCTED protons / antiprotons: true primary p / pbar of this MC collision ── + if (!trk.has_mcParticle()) { + continue; + } + const auto mc = trk.mcParticle_as(); + if (!mc.isPhysicalPrimary()) { + continue; + } + // Fill with RECONSTRUCTED kinematics (same variables as getEffWeight in processData()) + const float yReco = protonRapidity(trk); + if (trk.sign() > 0 && mc.pdgCode() == 2212) { + registryEff.fill(HIST("RecProton"), cent, trk.pt(), yReco); + } else if (trk.sign() < 0 && mc.pdgCode() == -2212) { + registryEff.fill(HIST("RecAntiProton"), cent, trk.pt(), yReco); + } + } + } + PROCESS_SWITCH(LambdaProtonBalanceFunction, processMC, "Efficiency from MC", false); + // ───────────────────────────────────────────────────────────────────── + // ── Run-level summary printed once at the end of the analysis job ───── // Called automatically by the O2 framework after all events are processed. // Prints totals accumulated in runTotalProtonBeforeVeto / runTotalProtonRemovedVeto. From 49bf5d077e013897b2507acd0d40ea85652e3298 Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Sat, 31 Oct 2026 05:10:55 +0530 Subject: [PATCH 6/8] Add AnalysisHelpers include to lambdaProtonBalanceFunction --- .../Tasks/lambdaProtonBalanceFunction.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index b97f2679952..969dbc5ca34 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include From 9a88d44c28303fe5afa0b9aafac07e5703bbb4bd Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Sat, 31 Oct 2026 05:14:39 +0530 Subject: [PATCH 7/8] Remove unused AnalysisHelpers include --- .../Tasks/lambdaProtonBalanceFunction.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index 969dbc5ca34..b97f2679952 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include From 59a331fc7182901f2a054139f757cd2de6ba2ebc Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Sat, 31 Oct 2026 05:23:59 +0530 Subject: [PATCH 8/8] Add AnalysisHelpers include to lambdaProtonBalanceFunction --- .../Tasks/lambdaProtonBalanceFunction.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index b97f2679952..648464f6973 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include