From 29d4afc724f1eaf296f54a08aa77fdeb0ad4fa21 Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Sat, 7 Nov 2026 20:41:26 +0530 Subject: [PATCH 1/4] Update 11: Refactor MC composition checks and add unweighted counts --- .../Tasks/lambdaProtonBalanceFunction.cxx | 393 +++++++----------- 1 file changed, 142 insertions(+), 251 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index 7dc7595998b..fad01cdc893 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -71,7 +72,7 @@ using MyTracks = soa::Join; -// MC-labelled versions used only by processMCEfficiency (efficiency maps) +// MC-labelled versions used by processMCEfficiency and processMCRecBF using MyTracksMC = soa::Join; using MyV0sMC = soa::Join; @@ -1297,14 +1298,6 @@ struct LambdaProtonBalanceFunction { void init(InitContext const&) { - if (doprocessMCComposition.value) { - if (doprocessData.value || doprocessMCRecBF.value || doprocessMCGenBF.value || doprocessMCEfficiency.value) { - LOGF(fatal, "processMCComposition requires processData, processMCRecBF, processMCGenBF and processMCEfficiency=false. processData defaults to true and must be disabled explicitly."); - } - if (cApplyEffCorr.value) { - LOGF(fatal, "processMCComposition requires cApplyEffCorr=false: composition stores unweighted counts and must not load efficiency maps."); - } - } if (static_cast(doprocessData.value) + static_cast(doprocessMCRecBF.value) + static_cast(doprocessMCGenBF.value) > 1) { @@ -1366,9 +1359,6 @@ struct LambdaProtonBalanceFunction { registryEff.add(name, name, {HistType::kTH3F, {axCent, axPt, axY}}); } } - if (doprocessMCComposition.value) { - bookMCComposition(); - } 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}}}); @@ -1376,6 +1366,20 @@ struct LambdaProtonBalanceFunction { 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}}}); registryOther.add("hNSelAntiLambda", "Number of selected AntiLambda candidates per event", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + + // ── Unweighted reconstructed counts per event ──────────────────────── + registryOther.add("hN_Lambda_reco1", "Stage 1: selected Lambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiLambda_reco1", "Stage 1: selected AntiLambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Proton_reco1", "Stage 1: selected Proton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiProton_reco1", "Stage 1: selected AntiProton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Lambda_PrimSec_reco", "Stage 2: PDG-matched primary + secondary Lambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiLambda_PrimSec_reco", "Stage 2: PDG-matched primary + secondary AntiLambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Proton_PrimSec_reco", "Stage 2: PDG-matched primary + secondary Proton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiProton_PrimSec_reco", "Stage 2: PDG-matched primary + secondary AntiProton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Lambda_prim_reco", "Stage 3: PDG-matched physical primary Lambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiLambda_prim_reco", "Stage 3: PDG-matched physical primary AntiLambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Proton_prim_reco", "Stage 3: PDG-matched physical primary Proton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiProton_prim_reco", "Stage 3: PDG-matched physical primary AntiProton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); // ── V0-daughter veto QA counters ───────────────────────────────────── // Proton veto counters registryOther.add("hNPrimProtonBeforeVeto", "Proton candidates before V0-daughter veto;N;Events", {HistType::kTH1F, {{200, 0.0f, 200.0f}}}); @@ -2205,10 +2209,9 @@ struct LambdaProtonBalanceFunction { for (int i = 0; i < 4; ++i) { hDaughters->GetXaxis()->SetBinLabel(i + 1, daughterLabels[i]); } - const std::string mode = doprocessData.value ? "processData" : doprocessMCRecBF.value ? "processMCRecBF" - : doprocessMCGenBF.value ? "processMCGenBF" - : doprocessMCComposition.value ? "processMCComposition" - : "none"; + const std::string mode = doprocessData.value ? "processData" : doprocessMCRecBF.value ? "processMCRecBF" + : doprocessMCGenBF.value ? "processMCGenBF" + : "none"; std::vector configLabels = { "activeBFMode=" + mode, "cUseFT0C=" + std::to_string(static_cast(cUseFT0C.value)), @@ -3185,19 +3188,49 @@ struct LambdaProtonBalanceFunction { // ───────────────────────────────────────────────────────────────────── } + private: + static bool usableMCIndex(aod::McParticles const* table, int64_t id) + { + // has_mcParticle() tests only id >= 0 in ASoA; also check the bound table range. + return table != nullptr && id >= 0 && id >= static_cast(table->offset()) && + id - static_cast(table->offset()) < table->size(); + } + + template + static std::pair matchRecoCandidate(TCandidate const& candidate, int expectedPDG, int64_t mcCollisionId) + { + if (!candidate.has_mcParticle()) { + return {false, false}; + } + // The label column binds the full truth table; the process argument may be + // sliced to the current MC collision. Validate the index before dereferencing. + const auto* truth = static_cast(candidate).getCurrent(); + const int64_t id = candidate.mcParticleId(); + if (!usableMCIndex(truth, id)) { + return {false, false}; + } + const auto mc = truth->rawIteratorAt(id - static_cast(truth->offset())); + if (mc.mcCollisionId() != mcCollisionId || mc.pdgCode() != expectedPDG) { + return {false, false}; + } + // First flag: PDG-matched; second flag: physical primary. + return {true, mc.isPhysicalPrimary()}; + } + + public: // Reconstructed candidates are compared with generated primary particles; // residual background and feed-down can prevent full closure. - template - void runRecoAnalysis(TCollision const& collision, aod::V0Datas const& V0s, - MyTracks const& tracks, float cent, CentRho2Set* cs) + template + void runRecoAnalysis(TCollision const& collision, TV0s const& V0s, + TTracks const& tracks, float cent, CentRho2Set* cs, [[maybe_unused]] int64_t mcCollisionId = -1) { // ====== Step 1: Initialise containers ====================================== std::unordered_set v0DaughterTrackIds; v0DaughterTrackIds.reserve(64); - std::vector selectedPrimProtons; - std::vector selectedPrimAntiProtons; - std::vector selectedLambdas; - std::vector selectedAntiLambdas; + std::vector selectedPrimProtons; + std::vector selectedPrimAntiProtons; + std::vector selectedLambdas; + std::vector selectedAntiLambdas; int nSelLambda = 0; int nSelAntiLambda = 0; @@ -3206,7 +3239,7 @@ struct LambdaProtonBalanceFunction { int nPairs_AntiLambda_PrimProton = 0; int nPairs_AntiLambda_PrimAntiProton = 0; - selectRecoV0s(collision, V0s, selectedLambdas, selectedAntiLambdas, v0DaughterTrackIds); + selectRecoV0s(collision, V0s, selectedLambdas, selectedAntiLambdas, v0DaughterTrackIds); nSelLambda = static_cast(selectedLambdas.size()); nSelAntiLambda = static_cast(selectedAntiLambdas.size()); constexpr float mLambdaPDG = o2::constants::physics::MassLambda; @@ -3217,8 +3250,8 @@ struct LambdaProtonBalanceFunction { { const float ctauFinal = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * mLambdaPDG; const float bgctauFinal = ctauFinal * v0.p() / mLambdaPDG; - const auto& dauPos = v0.posTrack_as(); - const auto& dauNeg = v0.negTrack_as(); + const auto& dauPos = v0.template posTrack_as(); + const auto& dauNeg = v0.template negTrack_as(); fillLambdaQA(LambdaQAStage::Final, v0, ctauFinal, bgctauFinal); fillDaughterQA(DaughterQAStage::Final, dauPos); fillDaughterQA(DaughterQAStage::Final, dauNeg); @@ -3240,8 +3273,8 @@ struct LambdaProtonBalanceFunction { { const float ctauFinal = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * mLambdaPDG; const float bgctauFinal = ctauFinal * v0.p() / mLambdaPDG; - const auto& dauPos = v0.posTrack_as(); - const auto& dauNeg = v0.negTrack_as(); + const auto& dauPos = v0.template posTrack_as(); + const auto& dauNeg = v0.template negTrack_as(); fillLambdaQA(LambdaQAStage::Final, v0, ctauFinal, bgctauFinal); fillDaughterQA(DaughterQAStage::Final, dauNeg); fillDaughterQA(DaughterQAStage::Final, dauPos); @@ -3442,7 +3475,7 @@ struct LambdaProtonBalanceFunction { // now fully populated. Veto set was built from validated daughters only. for (const auto& v0 : selectedLambdas) { - const auto& v0PosDau = v0.posTrack_as(); + const auto& v0PosDau = v0.template posTrack_as(); const float pt = v0.pt(); int bin = -1; for (size_t i = 0; i < state.ptEdges.size() - 1; ++i) { @@ -3697,7 +3730,7 @@ struct LambdaProtonBalanceFunction { } for (const auto& v0 : selectedAntiLambdas) { - const auto& v0NegDau = v0.negTrack_as(); + const auto& v0NegDau = v0.template negTrack_as(); const float pt = v0.pt(); int bin = -1; for (size_t i = 0; i < state.ptEdges.size() - 1; ++i) { @@ -4159,6 +4192,72 @@ struct LambdaProtonBalanceFunction { registryOther.fill(HIST("hNPairs_Lambda_PrimAntiProton"), static_cast(nPairs_Lambda_PrimAntiProton)); registryOther.fill(HIST("hNPairs_AntiLambda_PrimProton"), static_cast(nPairs_AntiLambda_PrimProton)); registryOther.fill(HIST("hNPairs_AntiLambda_PrimAntiProton"), static_cast(nPairs_AntiLambda_PrimAntiProton)); + + // ══ Stage counting: isolated from rho1/rho2 ═══════════════════════════ + registryOther.fill(HIST("hN_Lambda_reco1"), static_cast(selectedLambdas.size())); + registryOther.fill(HIST("hN_AntiLambda_reco1"), static_cast(selectedAntiLambdas.size())); + registryOther.fill(HIST("hN_Proton_reco1"), static_cast(selectedPrimProtons.size())); + registryOther.fill(HIST("hN_AntiProton_reco1"), static_cast(selectedPrimAntiProtons.size())); + + if constexpr (std::is_same_v, MyTracksMC> && std::is_same_v, MyV0sMC>) { + if (mcCollisionId != -1) { + int nLambdaPrimSec = 0; + int nAntiLambdaPrimSec = 0; + int nProtonPrimSec = 0; + int nAntiProtonPrimSec = 0; + int nLambdaPrim = 0; + int nAntiLambdaPrim = 0; + int nProtonPrim = 0; + int nAntiProtonPrim = 0; + + // Read only the final selected containers; every count has unit weight. + for (const auto& candidate : selectedLambdas) { + const auto [matched, primary] = matchRecoCandidate(candidate, 3122, mcCollisionId); + if (matched) { + ++nLambdaPrimSec; + if (primary) { + ++nLambdaPrim; + } + } + } + for (const auto& candidate : selectedAntiLambdas) { + const auto [matched, primary] = matchRecoCandidate(candidate, -3122, mcCollisionId); + if (matched) { + ++nAntiLambdaPrimSec; + if (primary) { + ++nAntiLambdaPrim; + } + } + } + for (const auto& candidate : selectedPrimProtons) { + const auto [matched, primary] = matchRecoCandidate(candidate, 2212, mcCollisionId); + if (matched) { + ++nProtonPrimSec; + if (primary) { + ++nProtonPrim; + } + } + } + for (const auto& candidate : selectedPrimAntiProtons) { + const auto [matched, primary] = matchRecoCandidate(candidate, -2212, mcCollisionId); + if (matched) { + ++nAntiProtonPrimSec; + if (primary) { + ++nAntiProtonPrim; + } + } + } + + registryOther.fill(HIST("hN_Lambda_PrimSec_reco"), static_cast(nLambdaPrimSec)); + registryOther.fill(HIST("hN_AntiLambda_PrimSec_reco"), static_cast(nAntiLambdaPrimSec)); + registryOther.fill(HIST("hN_Proton_PrimSec_reco"), static_cast(nProtonPrimSec)); + registryOther.fill(HIST("hN_AntiProton_PrimSec_reco"), static_cast(nAntiProtonPrimSec)); + registryOther.fill(HIST("hN_Lambda_prim_reco"), static_cast(nLambdaPrim)); + registryOther.fill(HIST("hN_AntiLambda_prim_reco"), static_cast(nAntiLambdaPrim)); + registryOther.fill(HIST("hN_Proton_prim_reco"), static_cast(nProtonPrim)); + registryOther.fill(HIST("hN_AntiProton_prim_reco"), static_cast(nAntiProtonPrim)); + } + } } void processData(soa::Filtered>::iterator const& collision, aod::V0Datas const& V0s, @@ -4186,7 +4285,7 @@ struct LambdaProtonBalanceFunction { auto* cs = bookBFEvent(collision, cent, nTracksINEL); runRecoAnalysis(collision, V0s, tracks, cent, cs); } - PROCESS_SWITCH(LambdaProtonBalanceFunction, processData, "Process for Data", true); + PROCESS_SWITCH(LambdaProtonBalanceFunction, processData, "Process for Data", false); // ══════════════════════════════════════════════════════════════════════════ // MC efficiency maps: Gen* from MC particles, Rec* from the reconstructed selection. @@ -4491,12 +4590,11 @@ struct LambdaProtonBalanceFunction { // ══ Matched-event BF selection (shared by reconstructed and generated modes) ══ using MatchedCollisions = soa::Join; - Preslice v0sPerCollisionData = aod::v0data::collisionId; Preslice tracksPerCollisionData = aod::track::collisionId; // This reference is conditional on accepted reconstructed events and excludes // MC collisions with missing or split reconstructed collisions. - // Select once for BF and composition; only BF books BF event histograms. + // Select once for matched events; only fillBF books BF event histograms. template void withMatchedEvent(aod::McCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, @@ -4544,18 +4642,20 @@ struct LambdaProtonBalanceFunction { // ══ Reconstructed BF in matched selected MC events ══ void processMCRecBF(aod::McCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, - aod::V0Datas const& allV0s, - MyTracks const& allTracks) + MyV0sMC const& allV0s, + MyTracksMC const& allTracks, + aod::McParticles const& /*mcParticles*/) { - // Unlabelled candidate tables preserve the complete data-like reco sample. - withMatchedBFEvent(mcCollision, collisions, allTracks, - [&](auto const& collision, MyTracks const& tracks, float cent, CentRho2Set* cs) { - auto V0s = allV0s.sliceBy(v0sPerCollisionData, collision.globalIndex()); - runRecoAnalysis(collision, V0s, tracks, cent, cs); - }); + // Labelled tables are joined 1:1 with the unlabelled tables: no row is dropped. + // Truth labels never enter Stage 1 reconstructed selection. + withMatchedEvent(mcCollision, collisions, allTracks, tracksPerCollision, + [&](auto const& collision, MyTracksMC const& tracks, float cent, CentRho2Set* cs) { + auto V0s = allV0s.sliceBy(v0sPerCollision, collision.globalIndex()); + runRecoAnalysis(collision, V0s, tracks, cent, cs, mcCollision.globalIndex()); + }); } PROCESS_SWITCH(LambdaProtonBalanceFunction, processMCRecBF, - "Reconstructed correlations in matched selected MC events", false); + "Reconstructed correlations in matched selected MC events", true); // ══ Generated BF in the identical matched selected MC events ══ void processMCGenBF(aod::McCollisions::iterator const& mcCollision, @@ -4677,220 +4777,11 @@ struct LambdaProtonBalanceFunction { PROCESS_SWITCH(LambdaProtonBalanceFunction, processMCGenBF, "Generated correlations in matched selected MC events", false); - // Book only for the exclusive composition mode; reuse Other_Hists. - void bookMCComposition() - { - // Identical axes to the efficiency maps: reconstructed centrality, pT, rapidity. - // Equal binning does not imply equal selections or establish valid closure. - const AxisSpec axCent(cCentBins, "reconstructed centrality (%)"); - const AxisSpec axPt{60, 0.0, 6.0, "reconstructed p_{T} (GeV/c)"}; - const AxisSpec axY{cRhoYBins.value, cRhoYMin.value, cRhoYMax.value, "reconstructed y"}; - // First/last bins are reserved for PDG codes below -10000 / above +10000. - const AxisSpec axMother{20003, -10001.5, 10001.5, "signed direct-mother PDG (out-of-range codes mapped to endpoints)"}; - const std::array categories = {"AllCandidates", "PrimarySignal", "SecondarySignal", - "WrongSpeciesOrSign", "Unmatched", "OtherMCCollision"}; - for (const char* species : {"Lambda", "AntiLambda", "Proton", "AntiProton"}) { - const std::string base = std::string("MCComposition/") + species + "/"; - for (const char* category : categories) { - const std::string name = base + "h3_" + category; - registryOther.add(name.c_str(), name.c_str(), {HistType::kTH3F, {axCent, axPt, axY}}); - } - auto totals = registryOther.add((base + "hCategoryTotals").c_str(), - "Selected reconstructed candidates;Category;Candidates", - {HistType::kTH1F, {{6, 0.5, 6.5}}}); - for (int i = 0; i < 6; ++i) { - totals->GetXaxis()->SetBinLabel(i + 1, categories[i]); - } - for (const char* signalClass : {"PrimarySignal", "SecondarySignal"}) { - const std::string name = base + "hMotherPDG_" + signalClass; - registryOther.add(name.c_str(), "Direct-mother associations (not exclusive candidate sources)", - {HistType::kTHnSparseF, {axMother, axPt, axCent}}); - auto multiplicity = registryOther.add((base + "hMotherMultiplicity_" + signalClass).c_str(), - "Valid recorded direct mothers per signal candidate;Mothers;Candidates", - {HistType::kTH1F, {{3, -0.5, 2.5}}}); - multiplicity->GetXaxis()->SetBinLabel(1, "0"); - multiplicity->GetXaxis()->SetBinLabel(2, "1"); - multiplicity->GetXaxis()->SetBinLabel(3, "2 or more"); - } - } - for (const char* species : {"Proton", "AntiProton"}) { - const std::string name = std::string("MCComposition/") + species + "/hMcMask"; - registryOther.add(name.c_str(), "Selected track MC mask (diagnostic only);mcMask;Candidates", - {HistType::kTH1F, {{65536, -0.5, 65535.5}}}); - } - registryOther.add("MCComposition/hAcceptedEvents", "Accepted composition events, including zero candidates;Events;Counts", - {HistType::kTH1F, {{1, 0.0, 1.0}}}); - // Store raw counts only, for merging and later bin-by-bin fractions: - // fSecondaryCandidates = Secondary / All - // fSecondarySignal = Secondary / (Primary + Secondary) - // fPrimaryCandidates = Primary / All - // fSignal = (Primary + Secondary) / All - // These denominators are not interchangeable; no fractions are calculated here. - } - - template - void fillCompositionCategory(TPrefix prefix, int category, float cent, float pt, float y) - { - // Bins 2..6 match the five exclusive categories in hCategoryTotals. - registryOther.fill(prefix + HIST("hCategoryTotals"), static_cast(category + 1)); - switch (category) { - case 1: - registryOther.fill(prefix + HIST("h3_PrimarySignal"), cent, pt, y); - break; - case 2: - registryOther.fill(prefix + HIST("h3_SecondarySignal"), cent, pt, y); - break; - case 3: - registryOther.fill(prefix + HIST("h3_WrongSpeciesOrSign"), cent, pt, y); - break; - case 4: - registryOther.fill(prefix + HIST("h3_Unmatched"), cent, pt, y); - break; - case 5: - registryOther.fill(prefix + HIST("h3_OtherMCCollision"), cent, pt, y); - break; - default: - break; - } - } - - static bool usableMCIndex(aod::McParticles const* table, int64_t id) - { - // has_mcParticle() tests only id >= 0 in ASoA; also check the bound table range. - return table != nullptr && id >= 0 && id >= static_cast(table->offset()) && - id - static_cast(table->offset()) < table->size(); - } - - template - void fillCompositionMothers(TPrefix prefix, TMc const& mc, bool primary, float pt, float cent) - { - int nMothers = 0; - // MothersIds is the actual direct-mother array in AnalysisDataModel.h. - // mothers_as() dereferences every stored index without range checks. - // Read mothersIds() and its bound table instead, validating each index first. - const auto* mothers = static_cast(mc) - .getCurrentRaw() - .template get(); - if (mc.has_mothers() && mothers) { - for (const auto motherId : mc.mothersIds()) { - if (!usableMCIndex(mothers, motherId)) { - continue; - } - const auto mother = mothers->rawIteratorAt(motherId - static_cast(mothers->offset())); - const int pdg = mother.pdgCode(); - const int recordedPDG = pdg < -10000 ? -10001 : pdg > 10000 ? 10001 - : pdg; - if (primary) { - registryOther.fill(prefix + HIST("hMotherPDG_PrimarySignal"), recordedPDG, pt, cent); - } else { - registryOther.fill(prefix + HIST("hMotherPDG_SecondarySignal"), recordedPDG, pt, cent); - } - ++nMothers; - } - } - // Count mother associations, not exclusive candidate sources: totals can exceed - // particle counts. No recorded mother does not imply primary; having a mother - // does not imply secondary. Only isPhysicalPrimary() defines that classification. - if (primary) { - registryOther.fill(prefix + HIST("hMotherMultiplicity_PrimarySignal"), std::min(nMothers, 2)); - } else { - registryOther.fill(prefix + HIST("hMotherMultiplicity_SecondarySignal"), std::min(nMothers, 2)); - } - } - - template - void fillMCCompositionCandidate(TPrefix prefix, TCandidate const& candidate, - int expectedPDG, int64_t mcCollisionId, - float cent, float pt, float y) - { - // Count candidates as selected, without deduplicating by truth ID. Ordinary - // TH3 under/overflow is retained; no extra acceptance or rho-grid cut is applied. - registryOther.fill(prefix + HIST("h3_AllCandidates"), cent, pt, y); - registryOther.fill(prefix + HIST("hCategoryTotals"), 1.f); - if (!candidate.has_mcParticle()) { - fillCompositionCategory(prefix, 4, cent, pt, y); - return; - } - // The label column binds the full truth table, whereas the process argument - // can be sliced to the current MC collision. Use the binding so a valid label - // pointing to another collision is OtherMCCollision rather than Unmatched. - const auto* truth = static_cast(candidate).getCurrent(); - const int64_t id = candidate.mcParticleId(); - if (!usableMCIndex(truth, id)) { - fillCompositionCategory(prefix, 4, cent, pt, y); - return; - } - const auto mc = truth->rawIteratorAt(id - static_cast(truth->offset())); - if (mc.mcCollisionId() != mcCollisionId) { - fillCompositionCategory(prefix, 5, cent, pt, y); - return; - } - if (mc.pdgCode() != expectedPDG) { - fillCompositionCategory(prefix, 3, cent, pt, y); - return; - } - const bool primary = mc.isPhysicalPrimary(); - // SecondarySignal means correctly identified and non-primary, not material-produced. - fillCompositionCategory(prefix, primary ? 1 : 2, cent, pt, y); - fillCompositionMothers(prefix, mc, primary, pt, cent); - // One All entry and exactly one exclusive category entry per selected candidate: - // All = Primary + Secondary + WrongSpeciesOrSign + Unmatched + OtherMCCollision. - } - - void processMCComposition(aod::McCollisions::iterator const& mcCollision, - soa::SmallGroups const& collisions, - MyV0sMC const& allV0s, - MyTracksMC const& allTracks, - aod::McParticles const& /*mcParticles*/) - { - // The McParticles input supplies framework label bindings; no truth filtering - // enters either shared reconstructed selection. All fills have unit weight. - withMatchedEvent(mcCollision, collisions, allTracks, tracksPerCollision, - [&](auto const& collision, MyTracksMC const& tracks, float cent, CentRho2Set*) { - registryOther.fill(HIST("MCComposition/hAcceptedEvents"), 0.5f); - fillRunConfig(); - auto V0s = allV0s.sliceBy(v0sPerCollision, collision.globalIndex()); - std::unordered_set v0DaughterTrackIds; - v0DaughterTrackIds.reserve(64); - std::vector lambdas, antiLambdas; - std::vector protons, antiProtons; - selectRecoV0s(collision, V0s, lambdas, antiLambdas, v0DaughterTrackIds); - // Reuse the pre-cleaning daughter set, including rejected shared-daughter V0s. - selectRecoProtons(tracks, v0DaughterTrackIds, protons, antiProtons); - for (const auto& v0 : lambdas) { - fillMCCompositionCandidate(HIST("MCComposition/Lambda/"), - v0, 3122, mcCollision.globalIndex(), cent, v0.pt(), v0.rapidity(1)); - } - for (const auto& v0 : antiLambdas) { - fillMCCompositionCandidate(HIST("MCComposition/AntiLambda/"), - v0, -3122, mcCollision.globalIndex(), cent, v0.pt(), v0.rapidity(2)); - } - // McTrackLabels::mcMask() is uint16_t: set bits indicate mismatches; - // bits 0..6 ITS layers, 12 ITSAB tracklet, 13 ITS-TPC, 14 noise, 15 fake. - // Record the complete mask for every selected track, never use it as a cut. - for (const auto& trk : protons) { - registryOther.fill(HIST("MCComposition/Proton/hMcMask"), trk.mcMask()); - fillMCCompositionCandidate(HIST("MCComposition/Proton/"), - trk, 2212, mcCollision.globalIndex(), cent, trk.pt(), protonRapidity(trk)); - } - for (const auto& trk : antiProtons) { - registryOther.fill(HIST("MCComposition/AntiProton/hMcMask"), trk.mcMask()); - fillMCCompositionCandidate(HIST("MCComposition/AntiProton/"), - trk, -2212, mcCollision.globalIndex(), cent, trk.pt(), protonRapidity(trk)); - } - }); - } - PROCESS_SWITCH(LambdaProtonBalanceFunction, processMCComposition, - "Reconstructed MC candidate composition and mother origins", 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. void endOfStream(EndOfStreamContext const&) { - if (doprocessMCComposition.value) { - return; // Composition persists raw counts only; no BF veto-fraction summary. - } const int64_t totalBefore = state.runTotalProtonBeforeVeto; const int64_t totalRemoved = state.runTotalProtonRemovedVeto; const int64_t totalAfter = totalBefore - totalRemoved; From 7b9c78a1d4df7d5b2ca9dad0db598f8af56a2f5b Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Sat, 7 Nov 2026 21:35:02 +0530 Subject: [PATCH 2/4] Refactor histogram labels and remove unneeded counts Updated histogram labels for Lambda and Proton counts to include clarity on event types. Removed redundant histogram registrations for unweighted counts. --- .../Tasks/lambdaProtonBalanceFunction.cxx | 242 ++++++++++-------- 1 file changed, 139 insertions(+), 103 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index fad01cdc893..32c09628ba2 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -58,7 +58,6 @@ #include #include #include -#include #include #include #include @@ -72,7 +71,7 @@ using MyTracks = soa::Join; -// MC-labelled versions used by processMCEfficiency and processMCRecBF +// MC-labelled versions used only by processMCEfficiency (efficiency maps) using MyTracksMC = soa::Join; using MyV0sMC = soa::Join; @@ -1366,20 +1365,18 @@ struct LambdaProtonBalanceFunction { 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}}}); registryOther.add("hNSelAntiLambda", "Number of selected AntiLambda candidates per event", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - - // ── Unweighted reconstructed counts per event ──────────────────────── - registryOther.add("hN_Lambda_reco1", "Stage 1: selected Lambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_AntiLambda_reco1", "Stage 1: selected AntiLambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_Proton_reco1", "Stage 1: selected Proton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_AntiProton_reco1", "Stage 1: selected AntiProton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_Lambda_PrimSec_reco", "Stage 2: PDG-matched primary + secondary Lambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_AntiLambda_PrimSec_reco", "Stage 2: PDG-matched primary + secondary AntiLambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_Proton_PrimSec_reco", "Stage 2: PDG-matched primary + secondary Proton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_AntiProton_PrimSec_reco", "Stage 2: PDG-matched primary + secondary AntiProton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_Lambda_prim_reco", "Stage 3: PDG-matched physical primary Lambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_AntiLambda_prim_reco", "Stage 3: PDG-matched physical primary AntiLambda per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_Proton_prim_reco", "Stage 3: PDG-matched physical primary Proton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); - registryOther.add("hN_AntiProton_prim_reco", "Stage 3: PDG-matched physical primary AntiProton per event (unweighted)", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Lambda_reco1", "Stage 1: selected reconstructed Lambda per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiLambda_reco1", "Stage 1: selected reconstructed AntiLambda per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Proton_reco1", "Stage 1: selected reconstructed Proton per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiProton_reco1", "Stage 1: selected reconstructed AntiProton per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Lambda_PrimSec_reco", "Stage 2: primary and secondary truth-matched Lambda per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiLambda_PrimSec_reco", "Stage 2: primary and secondary truth-matched AntiLambda per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Proton_PrimSec_reco", "Stage 2: primary and secondary truth-matched Proton per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiProton_PrimSec_reco", "Stage 2: primary and secondary truth-matched AntiProton per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Lambda_prim_reco", "Stage 3: physical-primary truth-matched Lambda per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiLambda_prim_reco", "Stage 3: physical-primary truth-matched AntiLambda per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_Proton_prim_reco", "Stage 3: physical-primary truth-matched Proton per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); + registryOther.add("hN_AntiProton_prim_reco", "Stage 3: physical-primary truth-matched AntiProton per event (unweighted);N;Events", {HistType::kTH1F, {{100, 0.0f, 100.0f}}}); // ── V0-daughter veto QA counters ───────────────────────────────────── // Proton veto counters registryOther.add("hNPrimProtonBeforeVeto", "Proton candidates before V0-daughter veto;N;Events", {HistType::kTH1F, {{200, 0.0f, 200.0f}}}); @@ -3188,36 +3185,128 @@ struct LambdaProtonBalanceFunction { // ───────────────────────────────────────────────────────────────────── } - private: - static bool usableMCIndex(aod::McParticles const* table, int64_t id) + void fillStage23Counts(int64_t /*mcCollisionId*/, + std::vector const& /*selectedLambdas*/, + std::vector const& /*selectedAntiLambdas*/, + std::vector const& /*selectedPrimProtons*/, + std::vector const& /*selectedPrimAntiProtons*/) { - // has_mcParticle() tests only id >= 0 in ASoA; also check the bound table range. - return table != nullptr && id >= 0 && id >= static_cast(table->offset()) && - id - static_cast(table->offset()) < table->size(); } - template - static std::pair matchRecoCandidate(TCandidate const& candidate, int expectedPDG, int64_t mcCollisionId) + void fillStage23Counts(int64_t mcCollisionId, + std::vector const& selectedLambdas, + std::vector const& selectedAntiLambdas, + std::vector const& selectedPrimProtons, + std::vector const& selectedPrimAntiProtons) { - if (!candidate.has_mcParticle()) { - return {false, false}; + // Stage 2 and Stage 3 counting; the selected reconstructed containers remain unchanged. + int nLambdaPrimSec = 0; + int nAntiLambdaPrimSec = 0; + int nProtonPrimSec = 0; + int nAntiProtonPrimSec = 0; + int nLambdaPrim = 0; + int nAntiLambdaPrim = 0; + int nProtonPrim = 0; + int nAntiProtonPrim = 0; + + for (const auto& candidate : selectedLambdas) { + if (!candidate.has_mcParticle()) { + continue; + } + const auto* truth = static_cast(candidate).getCurrent(); + const int64_t id = candidate.mcParticleId(); + if (!usableMCIndex(truth, id)) { + continue; + } + const auto mc = truth->rawIteratorAt(id - truth->offset()); + if (mc.mcCollisionId() != mcCollisionId) { + continue; + } + if (mc.pdgCode() != 3122) { + continue; + } + ++nLambdaPrimSec; + if (mc.isPhysicalPrimary()) { + ++nLambdaPrim; + } } - // The label column binds the full truth table; the process argument may be - // sliced to the current MC collision. Validate the index before dereferencing. - const auto* truth = static_cast(candidate).getCurrent(); - const int64_t id = candidate.mcParticleId(); - if (!usableMCIndex(truth, id)) { - return {false, false}; + + for (const auto& candidate : selectedAntiLambdas) { + if (!candidate.has_mcParticle()) { + continue; + } + const auto* truth = static_cast(candidate).getCurrent(); + const int64_t id = candidate.mcParticleId(); + if (!usableMCIndex(truth, id)) { + continue; + } + const auto mc = truth->rawIteratorAt(id - truth->offset()); + if (mc.mcCollisionId() != mcCollisionId) { + continue; + } + if (mc.pdgCode() != -3122) { + continue; + } + ++nAntiLambdaPrimSec; + if (mc.isPhysicalPrimary()) { + ++nAntiLambdaPrim; + } } - const auto mc = truth->rawIteratorAt(id - static_cast(truth->offset())); - if (mc.mcCollisionId() != mcCollisionId || mc.pdgCode() != expectedPDG) { - return {false, false}; + + for (const auto& candidate : selectedPrimProtons) { + if (!candidate.has_mcParticle()) { + continue; + } + const auto* truth = static_cast(candidate).getCurrent(); + const int64_t id = candidate.mcParticleId(); + if (!usableMCIndex(truth, id)) { + continue; + } + const auto mc = truth->rawIteratorAt(id - truth->offset()); + if (mc.mcCollisionId() != mcCollisionId) { + continue; + } + if (mc.pdgCode() != 2212) { + continue; + } + ++nProtonPrimSec; + if (mc.isPhysicalPrimary()) { + ++nProtonPrim; + } } - // First flag: PDG-matched; second flag: physical primary. - return {true, mc.isPhysicalPrimary()}; + + for (const auto& candidate : selectedPrimAntiProtons) { + if (!candidate.has_mcParticle()) { + continue; + } + const auto* truth = static_cast(candidate).getCurrent(); + const int64_t id = candidate.mcParticleId(); + if (!usableMCIndex(truth, id)) { + continue; + } + const auto mc = truth->rawIteratorAt(id - truth->offset()); + if (mc.mcCollisionId() != mcCollisionId) { + continue; + } + if (mc.pdgCode() != -2212) { + continue; + } + ++nAntiProtonPrimSec; + if (mc.isPhysicalPrimary()) { + ++nAntiProtonPrim; + } + } + + registryOther.fill(HIST("hN_Lambda_PrimSec_reco"), static_cast(nLambdaPrimSec)); + registryOther.fill(HIST("hN_AntiLambda_PrimSec_reco"), static_cast(nAntiLambdaPrimSec)); + registryOther.fill(HIST("hN_Proton_PrimSec_reco"), static_cast(nProtonPrimSec)); + registryOther.fill(HIST("hN_AntiProton_PrimSec_reco"), static_cast(nAntiProtonPrimSec)); + registryOther.fill(HIST("hN_Lambda_prim_reco"), static_cast(nLambdaPrim)); + registryOther.fill(HIST("hN_AntiLambda_prim_reco"), static_cast(nAntiLambdaPrim)); + registryOther.fill(HIST("hN_Proton_prim_reco"), static_cast(nProtonPrim)); + registryOther.fill(HIST("hN_AntiProton_prim_reco"), static_cast(nAntiProtonPrim)); } - public: // Reconstructed candidates are compared with generated primary particles; // residual background and feed-down can prevent full closure. template @@ -4193,71 +4282,12 @@ struct LambdaProtonBalanceFunction { registryOther.fill(HIST("hNPairs_AntiLambda_PrimProton"), static_cast(nPairs_AntiLambda_PrimProton)); registryOther.fill(HIST("hNPairs_AntiLambda_PrimAntiProton"), static_cast(nPairs_AntiLambda_PrimAntiProton)); - // ══ Stage counting: isolated from rho1/rho2 ═══════════════════════════ + // Stage 1 counting. registryOther.fill(HIST("hN_Lambda_reco1"), static_cast(selectedLambdas.size())); registryOther.fill(HIST("hN_AntiLambda_reco1"), static_cast(selectedAntiLambdas.size())); registryOther.fill(HIST("hN_Proton_reco1"), static_cast(selectedPrimProtons.size())); registryOther.fill(HIST("hN_AntiProton_reco1"), static_cast(selectedPrimAntiProtons.size())); - - if constexpr (std::is_same_v, MyTracksMC> && std::is_same_v, MyV0sMC>) { - if (mcCollisionId != -1) { - int nLambdaPrimSec = 0; - int nAntiLambdaPrimSec = 0; - int nProtonPrimSec = 0; - int nAntiProtonPrimSec = 0; - int nLambdaPrim = 0; - int nAntiLambdaPrim = 0; - int nProtonPrim = 0; - int nAntiProtonPrim = 0; - - // Read only the final selected containers; every count has unit weight. - for (const auto& candidate : selectedLambdas) { - const auto [matched, primary] = matchRecoCandidate(candidate, 3122, mcCollisionId); - if (matched) { - ++nLambdaPrimSec; - if (primary) { - ++nLambdaPrim; - } - } - } - for (const auto& candidate : selectedAntiLambdas) { - const auto [matched, primary] = matchRecoCandidate(candidate, -3122, mcCollisionId); - if (matched) { - ++nAntiLambdaPrimSec; - if (primary) { - ++nAntiLambdaPrim; - } - } - } - for (const auto& candidate : selectedPrimProtons) { - const auto [matched, primary] = matchRecoCandidate(candidate, 2212, mcCollisionId); - if (matched) { - ++nProtonPrimSec; - if (primary) { - ++nProtonPrim; - } - } - } - for (const auto& candidate : selectedPrimAntiProtons) { - const auto [matched, primary] = matchRecoCandidate(candidate, -2212, mcCollisionId); - if (matched) { - ++nAntiProtonPrimSec; - if (primary) { - ++nAntiProtonPrim; - } - } - } - - registryOther.fill(HIST("hN_Lambda_PrimSec_reco"), static_cast(nLambdaPrimSec)); - registryOther.fill(HIST("hN_AntiLambda_PrimSec_reco"), static_cast(nAntiLambdaPrimSec)); - registryOther.fill(HIST("hN_Proton_PrimSec_reco"), static_cast(nProtonPrimSec)); - registryOther.fill(HIST("hN_AntiProton_PrimSec_reco"), static_cast(nAntiProtonPrimSec)); - registryOther.fill(HIST("hN_Lambda_prim_reco"), static_cast(nLambdaPrim)); - registryOther.fill(HIST("hN_AntiLambda_prim_reco"), static_cast(nAntiLambdaPrim)); - registryOther.fill(HIST("hN_Proton_prim_reco"), static_cast(nProtonPrim)); - registryOther.fill(HIST("hN_AntiProton_prim_reco"), static_cast(nAntiProtonPrim)); - } - } + fillStage23Counts(mcCollisionId, selectedLambdas, selectedAntiLambdas, selectedPrimProtons, selectedPrimAntiProtons); } void processData(soa::Filtered>::iterator const& collision, aod::V0Datas const& V0s, @@ -4285,7 +4315,7 @@ struct LambdaProtonBalanceFunction { auto* cs = bookBFEvent(collision, cent, nTracksINEL); runRecoAnalysis(collision, V0s, tracks, cent, cs); } - PROCESS_SWITCH(LambdaProtonBalanceFunction, processData, "Process for Data", false); + PROCESS_SWITCH(LambdaProtonBalanceFunction, processData, "Process for Data", true); // ══════════════════════════════════════════════════════════════════════════ // MC efficiency maps: Gen* from MC particles, Rec* from the reconstructed selection. @@ -4590,11 +4620,12 @@ struct LambdaProtonBalanceFunction { // ══ Matched-event BF selection (shared by reconstructed and generated modes) ══ using MatchedCollisions = soa::Join; + Preslice v0sPerCollisionData = aod::v0data::collisionId; Preslice tracksPerCollisionData = aod::track::collisionId; // This reference is conditional on accepted reconstructed events and excludes // MC collisions with missing or split reconstructed collisions. - // Select once for matched events; only fillBF books BF event histograms. + // Select once for BF and composition; only BF books BF event histograms. template void withMatchedEvent(aod::McCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, @@ -4646,8 +4677,6 @@ struct LambdaProtonBalanceFunction { MyTracksMC const& allTracks, aod::McParticles const& /*mcParticles*/) { - // Labelled tables are joined 1:1 with the unlabelled tables: no row is dropped. - // Truth labels never enter Stage 1 reconstructed selection. withMatchedEvent(mcCollision, collisions, allTracks, tracksPerCollision, [&](auto const& collision, MyTracksMC const& tracks, float cent, CentRho2Set* cs) { auto V0s = allV0s.sliceBy(v0sPerCollision, collision.globalIndex()); @@ -4655,7 +4684,7 @@ struct LambdaProtonBalanceFunction { }); } PROCESS_SWITCH(LambdaProtonBalanceFunction, processMCRecBF, - "Reconstructed correlations in matched selected MC events", true); + "Reconstructed correlations in matched selected MC events", false); // ══ Generated BF in the identical matched selected MC events ══ void processMCGenBF(aod::McCollisions::iterator const& mcCollision, @@ -4777,6 +4806,13 @@ struct LambdaProtonBalanceFunction { PROCESS_SWITCH(LambdaProtonBalanceFunction, processMCGenBF, "Generated correlations in matched selected MC events", false); + static bool usableMCIndex(aod::McParticles const* table, int64_t id) + { + // has_mcParticle() tests only id >= 0 in ASoA; also check the bound table range. + return table != nullptr && id >= 0 && id >= static_cast(table->offset()) && + id - static_cast(table->offset()) < table->size(); + } + // ── 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 bb9a835d7053fd222a6401e75a46ff8027fe4624 Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Sun, 8 Nov 2026 00:10:43 +0530 Subject: [PATCH 3/4] Replace PDG codes with symbolic constants --- .../Tasks/lambdaProtonBalanceFunction.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index 32c09628ba2..d6dece42011 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -3222,7 +3222,7 @@ struct LambdaProtonBalanceFunction { if (mc.mcCollisionId() != mcCollisionId) { continue; } - if (mc.pdgCode() != 3122) { + if (mc.pdgCode() != PDG_t::kLambda0) { continue; } ++nLambdaPrimSec; @@ -3244,7 +3244,7 @@ struct LambdaProtonBalanceFunction { if (mc.mcCollisionId() != mcCollisionId) { continue; } - if (mc.pdgCode() != -3122) { + if (mc.pdgCode() != PDG_t::kLambda0Bar) { continue; } ++nAntiLambdaPrimSec; @@ -3266,7 +3266,7 @@ struct LambdaProtonBalanceFunction { if (mc.mcCollisionId() != mcCollisionId) { continue; } - if (mc.pdgCode() != 2212) { + if (mc.pdgCode() != PDG_t::kProton) { continue; } ++nProtonPrimSec; @@ -3288,7 +3288,7 @@ struct LambdaProtonBalanceFunction { if (mc.mcCollisionId() != mcCollisionId) { continue; } - if (mc.pdgCode() != -2212) { + if (mc.pdgCode() != PDG_t::kProtonBar) { continue; } ++nAntiProtonPrimSec; From b5ba13b86e8f656311f524f84861372afa136d19 Mon Sep 17 00:00:00 2001 From: Anoop1379 Date: Sun, 8 Nov 2026 00:29:53 +0530 Subject: [PATCH 4/4] Include TPdgCode header in lambdaProtonBalanceFunction Added TPdgCode header for particle data handling. --- .../Tasks/lambdaProtonBalanceFunction.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx index d6dece42011..4c1c3be98df 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaProtonBalanceFunction.cxx @@ -47,6 +47,7 @@ #include #include #include +#include #include #include