diff --git a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx index c76ec3d62d2..7dc6d877a8b 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx @@ -211,7 +211,7 @@ struct HfCorrelatorLcHadrons { Service pdg; int leadingIndex = 0; bool correlationStatus = false; - static constexpr size_t nDaughters{3u}; + static constexpr std::size_t NDaughters{3u}; TRandom3* rnd = new TRandom3(0); // Event Mixing for the Data Mode @@ -232,8 +232,10 @@ struct HfCorrelatorLcHadrons { Filter lcFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) != static_cast(0)) && (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); - // Preslice perTrueCollision = o2::aod::mcparticle::McCollisionId; Preslice perTrueCollision = o2::aod::mcparticle::mcCollisionId; + Preslice perCollisionID = aod::track::collisionId; + Preslice cand3ProngPerCol = aod::hf_cand::collisionId; + // configurable axis definition ConfigurableAxis binsMultiplicity{"binsMultiplicity", {VARIABLE_WIDTH, 0.0f, 2000.0f, 6000.0f, 100000.0f}, "Mixing bins - multiplicity"}; ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; @@ -441,7 +443,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPKPi(candidate), false); entryLcHadronGenInfo(false, false, 0); entryLcHadronMlInfo(outputMl[0], outputMl[1]); @@ -457,7 +459,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPiKP(candidate), false); entryLcHadronGenInfo(false, false, 0); entryLcHadronMlInfo(outputMl[0], outputMl[1]); @@ -694,7 +696,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPKPi(candidate), isLcSignal); if (fillTrkPID) { entryLcHadronPairTrkPID(track.tpcNSigmaPr(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tofNSigmaPr(), track.tofNSigmaKa(), track.tofNSigmaPi()); @@ -724,7 +726,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPiKP(candidate), isLcSignal); if (fillTrkPID) { entryLcHadronPairTrkPID(track.tpcNSigmaPr(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tofNSigmaPr(), track.tofNSigmaKa(), track.tofNSigmaPi()); @@ -801,12 +803,12 @@ struct HfCorrelatorLcHadrons { // prompt and non-prompt division std::vector listDaughters{}; - std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; - std::array prongsId; + std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; + std::array prongsId; listDaughters.clear(); RecoDecay::getDaughters(particle, &listDaughters, arrDaughLcPDG, 2); int counterDaughters = 0; - if (listDaughters.size() == nDaughters) { + if (listDaughters.size() == NDaughters) { for (const auto& dauIdx : listDaughters) { auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); counterDaughters += 1; diff --git a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx index 77c31d17969..21d3b4b6458 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx @@ -60,7 +60,7 @@ using BinningTypeMcGen = ColumnBinningPolicy lcSel; + Produces candSel; Configurable useSel8{"useSel8", true, "Flag for applying sel8 for collision selection"}; Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing"}; @@ -75,54 +75,42 @@ struct HfCorrelatorLcScHadronsSelection { using SelCollisions = soa::Join; using CandsLcDataFiltered = soa::Filtered>; using CandsLcMcRecFiltered = soa::Filtered>; + using CandsScMcRec = soa::Join; using CandidatesLcMcGen = soa::Join; - + using CandidatesScMcGen = soa::Join; // filter on selection of Lc and decay channel Lc->PKPi Filter lcFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) != static_cast(0)) && (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); - /// Code to select collisions with at least one Lc - for real data and data-like analysis - void processLcSelectionData(SelCollisions::iterator const& collision, - CandsLcDataFiltered const& candidates) + template + void selectionCollision(CollType const& collision, CandType const& candidates) { bool isSelColl = true; - bool isLcFound = true; + bool isCandFound = false; bool isSel8 = true; bool isNosameBunchPileUp = true; + double yCand = -999.; + const int chargeScZero = 0; if (doSelLcCollision) { for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yLc(candidate)) > yCandMax || candidate.pt() < ptCandMin) { - isLcFound = false; - continue; + + if constexpr (isCandSc) { + int8_t chargeCand = candidate.charge(); + + if (chargeCand == chargeScZero) { + yCand = hfHelper.ySc0(candidate); + } else { + yCand = hfHelper.yScPlusPlus(candidate); + } + + } else { + yCand = hfHelper.yLc(candidate); } - isLcFound = true; - break; - } - } - if (useSel8) { - isSel8 = collision.sel8(); - } - if (selNoSameBunchPileUpColl) { - isNosameBunchPileUp = static_cast(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); - } - isSelColl = isLcFound && isSel8 && isNosameBunchPileUp; - lcSel(isSelColl); - } - PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionData, "Process Lc Collision Selection Data", true); - void processLcSelectionMcRec(SelCollisions::iterator const& collision, - CandsLcMcRecFiltered const& candidates) - { - bool isSelColl = true; - bool isLcFound = true; - bool isSel8 = true; - bool isNosameBunchPileUp = true; - if (doSelLcCollision) { - for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yLc(candidate)) > yCandMax || candidate.pt() < ptCandMin) { - isLcFound = false; + if (std::abs(yCand) > yCandMax || candidate.pt() < ptCandMin) { + isCandFound = false; continue; } - isLcFound = true; + isCandFound = true; break; } } @@ -132,31 +120,76 @@ struct HfCorrelatorLcScHadronsSelection { if (selNoSameBunchPileUpColl) { isNosameBunchPileUp = static_cast(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); } - isSelColl = isLcFound && isSel8 && isNosameBunchPileUp; - lcSel(isSelColl); + isSelColl = isCandFound && isSel8 && isNosameBunchPileUp; + candSel(isSelColl); } - PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionMcRec, "Process Lc Selection McRec", false); - void processLcSelectionMcGen(aod::McCollision const&, - CandidatesLcMcGen const& mcParticles) + template + void selectionCollisionMcGen(CandType const& mcParticles) { - bool isLcFound = true; + bool isCandFound = false; + double massCand = -999.0; for (const auto& particle : mcParticles) { - if (std::abs(particle.pdgCode()) != Pdg::kLambdaCPlus) { - isLcFound = false; + + isCandFound = matchCandAndMass(particle, massCand); + if (!isCandFound) { continue; } - double yL = RecoDecay::y(particle.pVector(), MassLambdaCPlus); - if (std::abs(yL) > yCandMax || particle.pt() < ptCandMin) { - isLcFound = false; + + double yCand = RecoDecay::y(particle.pVector(), massCand); + if (std::abs(yCand) > yCandMax || particle.pt() < ptCandMin) { + isCandFound = false; continue; } - isLcFound = true; + + isCandFound = true; break; } - lcSel(isLcFound); + candSel(isCandFound); + } + + /// Code to select collisions with at least one Lc - for real data and data-like analysis + void processLcSelection(SelCollisions::iterator const& collision, + CandsLcDataFiltered const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelection, "Process Lc Collision Selection for Data and Mc", true); + + void processScSelection(SelCollisions::iterator const& collision, + aod::HfCandSc const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processScSelection, "Process Sc Collision Selection for Data and Mc", false); + + void processLcSelectionMcRec(SelCollisions::iterator const& collision, + CandsLcMcRecFiltered const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionMcRec, "Process Lc Selection McRec", false); + + void processScSelectionMcRec(SelCollisions::iterator const& collision, + CandsScMcRec const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processScSelectionMcRec, "Process Sc Selection McRec", false); + + void processLcSelectionMcGen(aod::McCollision const&, + CandidatesLcMcGen const& mcParticles) + { + selectionCollisionMcGen(mcParticles); } PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionMcGen, "Process Lc Selection McGen", false); + + void processScSelectionMcGen(aod::McCollision const&, + CandidatesScMcGen const& mcParticles) + { + selectionCollisionMcGen(mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processScSelectionMcGen, "Process Lc Selection McGen", false); }; // Lc-Hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via Mc truth) @@ -220,16 +253,15 @@ struct HfCorrelatorLcScHadrons { bool isNonPrompt = false; bool isSignal = false; - static constexpr size_t NDaughters{3u}; TRandom3* rnd = new TRandom3(0); - std::vector outputMl = {-1., -1., -1.}; + // std::vector outputMl = {-1., -1., -1.}; std::vector outputMlPKPi = {-1., -1., -1.}; std::vector outputMlPiKP = {-1., -1., -1.}; // Event Mixing for the Data Mode - using SelCollisionsWithSc = soa::Join; - using SelCollisionsWithLc = soa::Filtered>; - using SelCollisionsWithLcMc = soa::Filtered>; // collisionFilter applied + // using SelCollisionsWithSc = soa::Join; + using SelCollisions = soa::Filtered>; + using SelCollisionsMc = soa::Filtered>; // collisionFilter applied using CandsLcData = soa::Join; using CandsLcDataFiltered = soa::Filtered; @@ -238,6 +270,8 @@ struct HfCorrelatorLcScHadrons { using CandsLcMcRec = soa::Join; using CandsLcMcRecFiltered = soa::Filtered; using CandidatesLcMcGen = soa::Join; // flagLcFilter applied + using CandsScMcRec = soa::Join; + using CandidatesScMcGen = soa::Join; // Event Mixing for the MCGen Mode using McCollisionsSel = soa::Filtered>; using McParticlesSel = soa::Filtered; @@ -249,8 +283,11 @@ struct HfCorrelatorLcScHadrons { Filter lcFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) != static_cast(0)) && (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); - // Preslice perTrueCollision = o2::aod::mcparticle::McCollisionId; Preslice perTrueCollision = o2::aod::mcparticle::mcCollisionId; + Preslice perCollisionID = aod::track::collisionId; + Preslice cand3ProngPerCol = aod::hf_cand::collisionId; + Preslice csndScPerCol = aod::hf_cand::collisionId; + // configurable axis definition ConfigurableAxis binsMultiplicity{"binsMultiplicity", {VARIABLE_WIDTH, 0.0f, 2000.0f, 6000.0f, 100000.0f}, "Mixing bins - multiplicity"}; ConfigurableAxis binsZVtx{"binsZVtx", {VARIABLE_WIDTH, -10.0f, -2.5f, 2.5f, 10.0f}, "Mixing bins - z-vertex"}; @@ -279,7 +316,7 @@ struct HfCorrelatorLcScHadrons { AxisSpec axisBdtScore = {binsBdtScore, "Bdt score"}; AxisSpec axisPoolBin = {binsPoolBin, "PoolBin"}; AxisSpec axisRapidity = {100, -2, 2, "Rapidity"}; - AxisSpec axisSign = {2, -1, 1, "Sign"}; + AxisSpec axisSign = {5, -2.5, 2.5, "Sign"}; registry.add("hPtCand", "Lc,Hadron candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtLc}}); registry.add("hPtProng0", "Lc,Hadron candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtLc}}); @@ -297,6 +334,7 @@ struct HfCorrelatorLcScHadrons { registry.add("hCandBin", "Lc selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}); registry.add("hTracksBin", "Tracks selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}); registry.add("hMassLcVsPt", "Lc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{axisCandMass}, {axisPtLc}}}); + registry.add("hMassScVsPtVsSign", "Sc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});sign;entries", {HistType::kTH3F, {{axisCandMass}, {axisPtLc}, {axisSign}}}); registry.add("hMassLcData", "Lc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{axisCandMass}}}); registry.add("hLcPoolBin", "Lc candidates pool bin", {HistType::kTH1F, {axisPoolBin}}); registry.add("hTracksPoolBin", "Particles associated pool bin", {HistType::kTH1F, {axisPoolBin}}); @@ -329,7 +367,9 @@ struct HfCorrelatorLcScHadrons { registry.add("hPtCandMcGen", "Lc,Hadron particles - MC gen;particle #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtLc}}); registry.add("hYMcGen", "Lc,Hadron candidates - MC gen;candidate #it{#y};entries", {HistType::kTH1F, {axisRapidity}}); registry.add("hPtCandMcGenPrompt", "Lc,Hadron particles - MC Gen Prompt", {HistType::kTH1F, {axisPtLc}}); - registry.add("hPtCandMcGenNonPrompt", "Lc,Hadron particles - MC Gen Non Prompt", {HistType::kTH1F, {axisPtLc}}); + registry.add("hPtCandVsChargeMcGenPrompt", "Charm Hadron particles - MC Gen Prompt", {HistType::kTH2F, {{axisPtLc}, {axisSign}}}); + registry.add("hPtCandMcGenNonPrompt", "Charm Hadron particles - MC Gen Non Prompt", {HistType::kTH1F, {axisPtLc}}); + registry.add("hPtCandVsChargeMcGenNonPrompt", "Lc,Hadron particles - MC Gen Non Prompt", {HistType::kTH2F, {{axisPtLc}, {axisSign}}}); registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); registry.add("hEtaMcGen", "Lc,Hadron particles - MC Gen", {HistType::kTH1F, {axisEta}}); registry.add("hPhiMcGen", "Lc,Hadron particles - MC Gen", {HistType::kTH1F, {axisPhi}}); @@ -399,7 +439,7 @@ struct HfCorrelatorLcScHadrons { continue; auto chargeTrack = pdg->GetParticle(track.pdgCode())->Charge(); // Retrieve charge - registry.fill(HIST("hPtTracksVsSignGen"), track.pt(), chargeTrack / (2 * std::abs(chargeTrack))); + registry.fill(HIST("hPtTracksVsSignGen"), track.pt(), chargeTrack / (std::abs(chargeTrack))); } } template @@ -416,7 +456,7 @@ struct HfCorrelatorLcScHadrons { track.pt() * track.sign(), binPool, correlStatus); - entryCandHadronPairY(track.y() - yCand); + entryCandHadronPairY(track.rapidity(MassProton) - yCand); entryCandHadronMlInfo(outMl[0], outMl[1]); entryTrackRecoInfo(track.dcaXY(), track.dcaZ(), track.tpcNClsCrossedRows()); entryPairCandCharge(signCand); @@ -599,6 +639,7 @@ struct HfCorrelatorLcScHadrons { if (selLcPKPi) { registry.fill(HIST("hMassLcVsPt"), massCandPKPi, ptCand, efficiencyWeightCand); + registry.fill(HIST("hMassScVsPtVsSign"), massCandPKPi, ptCand, chargeCand, efficiencyWeightCand); registry.fill(HIST("hMassLcData"), massCandPKPi, efficiencyWeightCand); registry.fill(HIST("hSelectionStatusLcToPKPi"), selLcPKPi); if (isPrompt) { @@ -619,6 +660,7 @@ struct HfCorrelatorLcScHadrons { if (selLcPiKP) { registry.fill(HIST("hMassLcVsPt"), massCandPiKP, ptCand, efficiencyWeightCand); + registry.fill(HIST("hMassScVsPtVsSign"), massCandPKPi, ptCand, chargeCand, efficiencyWeightCand); registry.fill(HIST("hMassLcData"), massCandPiKP, efficiencyWeightCand); registry.fill(HIST("hSelectionStatusLcToPiKP"), selLcPiKP); if (isPrompt) { @@ -678,9 +720,9 @@ struct HfCorrelatorLcScHadrons { if (std::abs(motherTrk.pdgCode()) == kLambdaCPlus) continue; - registry.fill(HIST("hPtTracksVsSignRec"), track.pt(), track.sign() / 2.); + registry.fill(HIST("hPtTracksVsSignRec"), track.pt(), track.sign()); if (std::abs(mcParticle.pdgCode()) == kProton) - registry.fill(HIST("hPtTracksVsSignRecTrue"), track.pt(), track.sign() / 2.); + registry.fill(HIST("hPtTracksVsSignRecTrue"), track.pt(), track.sign()); } } @@ -827,99 +869,12 @@ struct HfCorrelatorLcScHadrons { } } - //} - - /// Lc-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processDataLc(SelCollisionsWithLc::iterator const& collision, - TracksData const& tracks, - CandsLcDataFiltered const& candidates, - aod::BCsWithTimestamps const&) - { - doSameEvent(collision, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataLc, "Process data", true); - - void processDataSc(SelCollisionsWithSc::iterator const& collision, - TracksData const& tracks, - aod::Tracks const&, - aod::HfCandSc const& candidates, - CandsLcData const&, - aod::BCsWithTimestamps const&) // MUST be last among index-compatible - { - doSameEvent(collision, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataSc, "Process data Sc", false); - - /// Lc-Hadron correlation process starts for McRec - void processMcRecLc(SelCollisionsWithLc::iterator const& collision, - TracksWithMc const& tracks, - CandsLcMcRecFiltered const& candidates, - aod::McParticles const& mcParticles) - { - doSameEvent(collision, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecLc, "Process Mc Reco mode", false); - - /// Lc-Hadron correlation process starts for McRec - void processMcRecSc(SelCollisionsWithSc::iterator const& collision, - TracksWithMc const& tracks, - aod::TracksWMc const&, - soa::Join const& candidates, - CandsLcData const&, - aod::McParticles const& mcParticles) - { - doSameEvent(collision, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecSc, "Process Mc Reco mode", false); - - void processDataMixedEventSc(SelCollisionsWithSc const& collisions, - TracksData const& tracks, - aod::Tracks const&, - aod::HfCandSc const& candidates, - CandsLcData const&) - { - doMixEvent(collisions, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventSc, "Process Mixed Event Data", false); - - void processDataMixedEventLc(SelCollisionsWithLc const& collisions, - CandsLcDataFiltered const& candidates, - TracksData const& tracks) - { - - doMixEvent(collisions, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventLc, "Process Mixed Event Data", false); - - void processMcRecMixedEventSc(SelCollisionsWithSc const& collisions, - TracksWithMc const& tracks, - aod::TracksWMc const&, - soa::Join const& candidates, - CandsLcData const&, - aod::McParticles const& mcParticles) - { - doMixEvent(collisions, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventSc, "Process Mixed Event McRec", false); - - void processMcRecMixedEventLc(SelCollisionsWithLc const& collisions, - CandsLcMcRecFiltered const& candidates, - TracksWithMc const& tracks, - aod::McParticles const& mcParticles) + template + void doSameEventMcGen(CollisionType const& mcCollision, PartType const& mcParticles) { - doMixEvent(collisions, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventLc, "Process Mixed Event McRec", false) - /// Lc-Hadron correlation pair builder - for Mc Gen-level analysis - void processMcGen(SelCollisionsWithLcMc::iterator const& mcCollision, - CandidatesLcMcGen const& mcParticles) - { - int counterLcHadron = 0; + int counterCharmCand = 0; registry.fill(HIST("hMcEvtCount"), 0); - BinningTypeMcGen corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), mcCollision.multMCFT0A())); registry.fill(HIST("hMultFT0AMcGen"), mcCollision.multMCFT0A()); @@ -928,48 +883,70 @@ struct HfCorrelatorLcScHadrons { if (correlateLcWithLeadingParticle) { leadingIndex = findLeadingParticleMcGen(mcParticles, etaTrackMax.value, ptTrackMin.value); } - // Mc Gen level for (const auto& particle : mcParticles) { - if (std::abs(particle.pdgCode()) != Pdg::kLambdaCPlus) { - continue; - } - if (!TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { + + double massCand = -999.0; + bool isCandFound = isCandSc ? matchCandAndMass(particle, massCand) : matchCandAndMass(particle, massCand); + if (!isCandFound) { continue; } - double yL = RecoDecay::y(particle.pVector(), MassLambdaCPlus); - if (std::abs(yL) > yCandGenMax || particle.pt() < ptCandMin) { + double yCand = RecoDecay::y(particle.pVector(), massCand); + + if (std::abs(yCand) > yCandGenMax || particle.pt() < ptCandMin) { continue; } registry.fill(HIST("hCandBin"), poolBin); registry.fill(HIST("hPtCandMcGen"), particle.pt()); registry.fill(HIST("hEtaMcGen"), particle.eta()); registry.fill(HIST("hPhiMcGen"), RecoDecay::constrainAngle(particle.phi(), -PIHalf)); - registry.fill(HIST("hYMcGen"), yL); + registry.fill(HIST("hYMcGen"), yCand); + + int8_t chargeLc = pdg->GetParticle(particle.pdgCode())->Charge(); // Retrieve charge + if (chargeLc != 0) { + chargeLc = chargeLc / std::abs(chargeLc); + } isPrompt = particle.originMcGen() == RecoDecay::OriginType::Prompt; isNonPrompt = particle.originMcGen() == RecoDecay::OriginType::NonPrompt; if (isPrompt) { registry.fill(HIST("hPtCandMcGenPrompt"), particle.pt()); + registry.fill(HIST("hPtCandVsChargeMcGenPrompt"), particle.pt(), chargeLc); } else if (isNonPrompt) { registry.fill(HIST("hPtCandMcGenNonPrompt"), particle.pt()); + registry.fill(HIST("hPtCandVsChargeMcGenNonPrompt"), particle.pt(), chargeLc); } - // prompt and non-prompt division + static constexpr std::size_t NDaughtersSc{4u}; + static constexpr std::size_t NDaughtersLc{3u}; std::vector listDaughters{}; - std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; - std::array prongsId; listDaughters.clear(); - RecoDecay::getDaughters(particle, &listDaughters, arrDaughLcPDG, 2); + const std::size_t nDaughtersExpected = isCandSc ? NDaughtersSc : NDaughtersLc; + + if (isCandSc) { + if (massCand == o2::constants::physics::MassSigmaC0 || massCand == o2::constants::physics::MassSigmaCStar0) { + std::array arrDaughSc0PDG = {kProton, -kKPlus, kPiPlus, kPiMinus}; + RecoDecay::getDaughters(particle, &listDaughters, arrDaughSc0PDG, 2); + } else { + std::array arrDaughScPlusPDG = {kProton, -kKPlus, kPiPlus, kPiPlus}; + RecoDecay::getDaughters(particle, &listDaughters, arrDaughScPlusPDG, 2); + } + } else { + std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; + RecoDecay::getDaughters(particle, &listDaughters, arrDaughLcPDG, 2); + } + int counterDaughters = 0; - if (listDaughters.size() == NDaughters) { + std::vector prongsId(nDaughtersExpected); + if (listDaughters.size() == nDaughtersExpected) { for (const auto& dauIdx : listDaughters) { auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); counterDaughters += 1; prongsId[counterDaughters - 1] = daughI.globalIndex(); } } - counterLcHadron++; + counterCharmCand++; + // Lc Hadron correlation dedicated section // if it's a Lc particle, search for Hadron and evalutate correlations registry.fill(HIST("hcountCandtriggersMcGen"), 0, particle.pt()); // to count trigger Lc for normalisation @@ -977,7 +954,8 @@ struct HfCorrelatorLcScHadrons { if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { continue; } - if (particleAssoc.globalIndex() == prongsId[0] || particleAssoc.globalIndex() == prongsId[1] || particleAssoc.globalIndex() == prongsId[2]) { + + if (std::find(prongsId.begin(), prongsId.end(), particleAssoc.globalIndex()) != prongsId.end()) { if (!storeAutoCorrelationFlag) { continue; } @@ -1001,33 +979,132 @@ struct HfCorrelatorLcScHadrons { } } - int8_t chargeLc = pdg->GetParticle(particle.pdgCode())->Charge(); // Retrieve charge - int8_t chargeAssoc = pdg->GetParticle(particleAssoc.pdgCode())->Charge(); // Retrieve charge - int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); + int8_t chargeAssoc = pdg->GetParticle(particleAssoc.pdgCode())->Charge(); // Retrieve charge + chargeAssoc = chargeAssoc / std::abs(chargeAssoc); registry.fill(HIST("hPtParticleAssocMcGen"), particleAssoc.pt()); entryCandHadronPair(getDeltaPhi(particleAssoc.phi(), particle.phi()), particleAssoc.eta() - particle.eta(), - particle.pt() * chargeLc / std::abs(chargeLc), - particleAssoc.pt() * chargeAssoc / std::abs(chargeAssoc), + particle.pt(), + particleAssoc.pt() * chargeAssoc, poolBin, correlationStatus); - entryCandHadronPairY(particleAssoc.y() - yL); - entryCandHadronRecoInfo(MassLambdaCPlus, true); + entryCandHadronPairY(particleAssoc.y() - yCand); + entryCandHadronRecoInfo(massCand, true); entryCandHadronGenInfo(isPrompt, particleAssoc.isPhysicalPrimary(), trackOrigin); + entryPairCandCharge(chargeLc); } // end inner loop } // end outer loop - registry.fill(HIST("hcountCandHadronPerEvent"), counterLcHadron); + registry.fill(HIST("hcountCandHadronPerEvent"), counterCharmCand); registry.fill(HIST("hZvtx"), mcCollision.posZ()); } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGen, "Process Mc Gen mode", false); - void processMcGenMixedEvent(SelCollisionsWithLcMc const& collisions, + //} + + /// Lc-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) + void processDataLc(SelCollisions::iterator const& collision, + TracksData const& tracks, + CandsLcDataFiltered const& candidates, + aod::BCsWithTimestamps const&) + { + doSameEvent(collision, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataLc, "Process data", true); + + void processDataSc(SelCollisions::iterator const& collision, + TracksData const& tracks, + aod::Tracks const&, + aod::HfCandSc const& candidates, + CandsLcData const&, + aod::BCsWithTimestamps const&) // MUST be last among index-compatible + { + doSameEvent(collision, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataSc, "Process data Sc", false); + + /// Lc-Hadron correlation process starts for McRec + void processMcRecLc(SelCollisions::iterator const& collision, + TracksWithMc const& tracks, + CandsLcMcRecFiltered const& candidates, + aod::McParticles const& mcParticles) + { + doSameEvent(collision, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecLc, "Process Mc Reco mode", false); + + /// Lc-Hadron correlation process starts for McRec + void processMcRecSc(SelCollisions::iterator const& collision, + TracksWithMc const& tracks, + aod::TracksWMc const&, + CandsScMcRec const& candidates, + CandsLcData const&, + aod::McParticles const& mcParticles) + { + doSameEvent(collision, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecSc, "Process Mc Reco mode", false); + + void processDataMixedEventSc(SelCollisions const& collisions, + TracksData const& tracks, + aod::Tracks const&, + aod::HfCandSc const& candidates, + CandsLcData const&) + { + doMixEvent(collisions, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventSc, "Process Mixed Event Data", false); + + void processDataMixedEventLc(SelCollisions const& collisions, + CandsLcDataFiltered const& candidates, + TracksData const& tracks) + { + + doMixEvent(collisions, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventLc, "Process Mixed Event Data", false); + + void processMcRecMixedEventSc(SelCollisions const& collisions, + TracksWithMc const& tracks, + aod::TracksWMc const&, + soa::Join const& candidates, + CandsLcData const&, + aod::McParticles const& mcParticles) + { + doMixEvent(collisions, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventSc, "Process Mixed Event McRec", false); + + void processMcRecMixedEventLc(SelCollisions const& collisions, + CandsLcMcRecFiltered const& candidates, + TracksWithMc const& tracks, + aod::McParticles const& mcParticles) + { + doMixEvent(collisions, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventLc, "Process Mixed Event McRec", false) + + /// Lc-Hadron correlation pair builder - for Mc Gen-level analysis + void processMcGenLc(SelCollisionsMc::iterator const& mcCollision, + CandidatesLcMcGen const& mcParticles) + { + doSameEventMcGen(mcCollision, mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGenLc, "Process Mc Gen Lc mode", false); + + void processMcGenSc(SelCollisionsMc::iterator const& mcCollision, + CandidatesScMcGen const& mcParticles) + { + doSameEventMcGen(mcCollision, mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGenSc, "Process Mc Gen Sc mode", false); + + void processMcGenMixedEvent(SelCollisionsMc const& collisions, CandidatesLcMcGen const& mcParticles) { BinningTypeMcGen corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair pairMcGen{corrBinningMcGen, numberEventsMixed, -1, collisions, tracksTuple, &cache}; + Pair pairMcGen{corrBinningMcGen, numberEventsMixed, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, tracks1, c2, tracks2] : pairMcGen) { poolBin = corrBinningMcGen.getBin(std::make_tuple(c1.posZ(), c1.multMCFT0A())); for (const auto& [candidate, particleAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { diff --git a/PWGHF/HFC/Utils/utilsCorrelations.h b/PWGHF/HFC/Utils/utilsCorrelations.h index 90f7b8524d9..b830eedcfef 100644 --- a/PWGHF/HFC/Utils/utilsCorrelations.h +++ b/PWGHF/HFC/Utils/utilsCorrelations.h @@ -45,12 +45,16 @@ enum PairSign { LcNegTrkNeg }; +constexpr float PhiTowardMax{o2::constants::math::PIThird}; +constexpr float PhiAwayMin{2.f * o2::constants::math::PIThird}; +constexpr float PhiAwayMax{4.f * o2::constants::math::PIThird}; + template Region getRegion(T const deltaPhi) { - if (std::abs(deltaPhi) < o2::constants::math::PIThird) { + if (std::abs(deltaPhi) < PhiTowardMax) { return Toward; - } else if (deltaPhi > 2. * o2::constants::math::PIThird && deltaPhi < 4. * o2::constants::math::PIThird) { + } else if (deltaPhi > PhiAwayMin && deltaPhi < PhiAwayMax) { return Away; } else { return Transverse; @@ -119,6 +123,70 @@ bool passPIDSelection(Atrack const& track, SpeciesContainer const mPIDspecies, return true; // Passed all checks } +/// @brief Selects a candidate based on its PDG code, decay channel, and assigns the corresponding mass. +/// +/// @tparam isScCandidate Boolean template parameter: +/// - `true` to check for Sigma_c candidates +/// - `false` to check for Lambda_c candidates +/// @tparam McParticleType Type representing the MC particle, must provide `pdgCode()` and `flagMcMatchGen()` +/// +/// @param[in] particle MC particle whose PDG code and decay flag are evaluated +/// @param[out] massCand Mass of the matched candidate is set here, if a valid match is found +/// +/// @return `true` if candidate matches expected PDG and decay flag, and mass is set; `false` otherwise +template +bool matchCandAndMass(McParticleType const& particle, double& massCand) +{ + const auto pdgCand = std::abs(particle.pdgCode()); + const auto matchGenFlag = std::abs(particle.flagMcMatchGen()); + + // Validate PDG code based on candidate type + if (isScCandidate) { + if (!(pdgCand == o2::constants::physics::Pdg::kSigmaC0 || + pdgCand == o2::constants::physics::Pdg::kSigmaCPlusPlus || + pdgCand == o2::constants::physics::Pdg::kSigmaCStar0 || + pdgCand == o2::constants::physics::Pdg::kSigmaCStarPlusPlus)) { + return false; + } + } else { + if (pdgCand != o2::constants::physics::Pdg::kLambdaCPlus) { + return false; + } + } + + // Map decay type to mass + switch (matchGenFlag) { + case BIT(aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi): { + massCand = o2::constants::physics::MassSigmaC0; + return true; + } + + case BIT(aod::hf_cand_sigmac::DecayType::ScStar0ToPKPiPi): { + massCand = o2::constants::physics::MassSigmaCStar0; + return true; + } + + case BIT(aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi): { + massCand = o2::constants::physics::MassSigmaCStarPlusPlus; + return true; + } + + case BIT(aod::hf_cand_sigmac::DecayType::ScStarPlusPlusToPKPiPi): { + massCand = o2::constants::physics::MassSigmaCStarPlusPlus; + return true; + } + + case hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi: { + massCand = o2::constants::physics::MassLambdaCPlus; + return true; + } + + default: { + return false; + } + } +} + // ========= Find Leading Particle ============== template //// FIXME: 14 days int findLeadingParticle(TTracks const& tracks, T1 const etaTrackMax)