From 03e347b54056d39be4e70fb4302b97ccd11e00cc Mon Sep 17 00:00:00 2001 From: scannito Date: Sat, 21 Feb 2026 14:29:50 +0100 Subject: [PATCH 1/2] New tables for purity studies --- .../DataModel/LFPhiStrangeCorrelationTables.h | 108 ++- .../Strangeness/phiStrangeCorrelator.cxx | 653 +++++++++++++++--- .../Strangeness/phiStrangeCorrelation.cxx | 449 +++--------- 3 files changed, 742 insertions(+), 468 deletions(-) diff --git a/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h b/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h index 3e12bad91e3..e72662a92e5 100644 --- a/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h +++ b/PWGLF/DataModel/LFPhiStrangeCorrelationTables.h @@ -22,6 +22,48 @@ namespace o2::aod { +namespace lf_selection_event +{ +DECLARE_SOA_COLUMN(DefaultSel, defaultSel, bool); +DECLARE_SOA_COLUMN(PhimesonSel, phimesonSel, bool); +} // namespace lf_selection_event + +/*DECLARE_SOA_TABLE(PhiStrangeDefEvtSelDataLike, "AOD", "DEFEVTSELDATA", + lf_selection_event::DefaultSel); + +DECLARE_SOA_TABLE(PhiStrangeDefEvtSelMcGen, "AOD", "DEFEVTSELMCGEN", + lf_selection_event::DefaultSel);*/ + +DECLARE_SOA_TABLE(PhiStrangeEvtSelDataLike, "AOD", "EVTSELDATA", + lf_selection_event::DefaultSel, + lf_selection_event::PhimesonSel); + +DECLARE_SOA_TABLE(PhiStrangeEvtSelMcGen, "AOD", "EVTSELMCGEN", + lf_selection_event::DefaultSel, + lf_selection_event::PhimesonSel); + +/*namespace lf_selection_default_collision +{ +DECLARE_SOA_COLUMN(DefaultSel, defaultSel, bool); +} // namespace lf_selection_default_collision + +DECLARE_SOA_TABLE(DefaultSelectionData, "AOD", "DEFSELDATA", + lf_selection_default_collision::DefaultSel); + +DECLARE_SOA_TABLE(DefaultSelectionMcGen, "AOD", "DEFSELMCGEN", + lf_selection_default_collision::DefaultSel); + +namespace lf_selection_phi_collision +{ +DECLARE_SOA_COLUMN(PhimesonSel, phimesonSel, bool); +} // namespace lf_selection_phi_collision + +DECLARE_SOA_TABLE(PhimesonSelectionData, "AOD", "PHIINCOLLDATA", + lf_selection_phi_collision::PhimesonSel); + +DECLARE_SOA_TABLE(PhimesonSelectionMcGen, "AOD", "PHIINCOLLMCGEN", + lf_selection_phi_collision::PhimesonSel);*/ + namespace lf_selection_phi_candidate { DECLARE_SOA_INDEX_COLUMN(Collision, collision); @@ -64,19 +106,67 @@ DECLARE_SOA_TABLE(PhimesonCandidatesMcGen, "AOD", "PHICANDMCGEN", lf_selection_phi_candidate::Phi, lf_selection_phi_candidate::InMassRegion); -namespace lf_selection_phi_collision +namespace lf_selection_k0s_reduced { -DECLARE_SOA_COLUMN(PhimesonSel, phimesonSel, bool); -} // namespace lf_selection_phi_collision +DECLARE_SOA_INDEX_COLUMN(Collision, collision); -DECLARE_SOA_TABLE(PhimesonSelectionData, "AOD", "PHIINCOLLDATA", - lf_selection_phi_collision::PhimesonSel); +DECLARE_SOA_COLUMN(M, m, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(Phi, phi, float); -/*DECLARE_SOA_TABLE(PhimesonSelectionMcReco, "AOD", "PHIINCOLLMCRECO", - lf_selection_phi_collision::PhimesonSel);*/ +DECLARE_SOA_DYNAMIC_COLUMN(InMassRegion, inMassRegion, + [](float m, float minM, float maxM) -> bool { + return (m >= minM && m <= maxM); + }); +} // namespace lf_selection_k0s_reduced -DECLARE_SOA_TABLE(PhimesonSelectionMcGen, "AOD", "PHIINCOLLMCGEN", - lf_selection_phi_collision::PhimesonSel); +DECLARE_SOA_TABLE(K0sReducedCandidatesData, "AOD", "K0SCANDDATA", + soa::Index<>, + lf_selection_k0s_reduced::CollisionId, + lf_selection_k0s_reduced::M, + lf_selection_k0s_reduced::Pt, + lf_selection_k0s_reduced::Y, + lf_selection_k0s_reduced::Phi, + lf_selection_k0s_reduced::InMassRegion); + +DECLARE_SOA_TABLE(K0sReducedCandidatesMcReco, "AOD", "K0SCANDMCRECO", + soa::Index<>, + lf_selection_k0s_reduced::CollisionId, + lf_selection_k0s_reduced::M, + lf_selection_k0s_reduced::Pt, + lf_selection_k0s_reduced::Y, + lf_selection_k0s_reduced::Phi, + lf_selection_k0s_reduced::InMassRegion); + +namespace lf_selection_pion_track +{ +DECLARE_SOA_INDEX_COLUMN(Collision, collision); + +DECLARE_SOA_COLUMN(NSigmaTPC, nSigmaTPC, float); +DECLARE_SOA_COLUMN(NSigmaTOF, nSigmaTOF, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Y, y, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +} // namespace lf_selection_pion_track + +DECLARE_SOA_TABLE(PionTracksData, "AOD", "PITRACKSDATA", + soa::Index<>, + lf_selection_pion_track::CollisionId, + lf_selection_pion_track::NSigmaTPC, + lf_selection_pion_track::NSigmaTOF, + lf_selection_pion_track::Pt, + lf_selection_pion_track::Y, + lf_selection_pion_track::Phi); + +DECLARE_SOA_TABLE(PionTracksMcReco, "AOD", "PITRACKSMCRECO", + soa::Index<>, + lf_selection_pion_track::CollisionId, + lf_selection_pion_track::NSigmaTPC, + lf_selection_pion_track::NSigmaTOF, + lf_selection_pion_track::Pt, + lf_selection_pion_track::Y, + lf_selection_pion_track::Phi); } // namespace o2::aod #endif // PWGLF_DATAMODEL_LFPHISTRANGECORRELATIONTABLES_H_ diff --git a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx index 169e84a982b..211302881a7 100644 --- a/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx +++ b/PWGLF/TableProducer/Strangeness/phiStrangeCorrelator.cxx @@ -14,6 +14,7 @@ /// \author Stefano Cannito (stefano.cannito@cern.ch) #include "PWGLF/DataModel/LFPhiStrangeCorrelationTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/mcCentrality.h" #include "PWGLF/Utils/inelGt.h" @@ -43,6 +44,7 @@ #include #include #include +#include #include #include @@ -50,6 +52,8 @@ #include #include #include +#include +#include #include #include #include @@ -65,7 +69,10 @@ struct PhiMesonCandProducer { Produces phimesonCandidatesMcReco; Produces phimesonCandidatesMcGen; - HistogramRegistry histos{"phiCandidates", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry histos{"phimesonCandidates", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable on multiplicity bins + Configurable> binsMult{"binsMult", {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}, "Multiplicity bin limits"}; // Configurables for phi's daughter tracks selection struct : ConfigurableGroup { @@ -88,15 +95,28 @@ struct PhiMesonCandProducer { // Configurables on phi selection struct : ConfigurableGroup { - Configurable maxMPhi{"maxMPhi", 1.5f, "Maximum mass for Phi candidates"}; + Configurable maxMPhi{"maxMPhi", 1.2f, "Maximum mass for Phi candidates"}; Configurable minPhiPt{"minPhiPt", 0.4f, "Minimum pT for Phi candidates"}; Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; } phiConfigs; + // Configurables on phi pT bins + Configurable> binspTPhi{"binspTPhi", {0.4, 0.8, 1.4, 2.0, 2.8, 4.0, 6.0, 10.0}, "pT bin limits for Phi"}; + + // Filter on default selected collisions + // Filter collisionFilter = aod::lf_selection_default_collision::defaultSel == true; + // Filter collisionFilter = aod::lf_selection_event::defaultSel == true; + // Defining the type of the collisions for data and MC - using SelCollisions = soa::Join; + using SelCollisions = soa::Join; using SimCollisions = soa::Join; + /*using SelCollisions = soa::Join; + using SimCollisions = soa::Join; + + using FilteredSelCollisions = soa::Filtered; + using FilteredSimCollisions = soa::Filtered;*/ + // Defining the type of the phi's daughter tracks for data and MC using FullTracks = soa::Join; using FullMCTracks = soa::Join; @@ -116,9 +136,18 @@ struct PhiMesonCandProducer { void init(InitContext&) { + AxisSpec binnedmultAxis{(std::vector)binsMult, "centFT0M"}; + AxisSpec binnedpTPhiAxis{(std::vector)binspTPhi, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec massPhiAxis = {200, 0.9f, 1.2f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; - histos.add("h1PhiCandidateMass", "Phi candidate invariant mass", kTH1F, {massPhiAxis}); + histos.add("h3PhiCandidatesMass", "Phi candidate invariant mass", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + + // Phi's daughter tracks information + /*histos.add("hEta", "Eta of Kaon candidates", kTH1F, {{100, -1.0f, 1.0f}}); + histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); + histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); + histos.add("h2DauTracksPhiDCAxy", "DCAxy distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + histos.add("h2DauTracksPhiDCAz", "DCAz distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}});*/ } // Topological track selection @@ -167,19 +196,53 @@ struct PhiMesonCandProducer { return mother; } - void processData(SelCollisions::iterator const& collision, FullTracks const&) + template + void processPhiCandidates(const T& collision, std::optional> mcParticlesOpt = std::nullopt) { - auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - + // Compile-time selection of the track partition to use based on the type of the analysis (Data or MCReco) + auto posThisColl = [&]() { + if constexpr (isMC) + return posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + else + return posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + }(); + + auto negThisColl = [&]() { + if constexpr (isMC) + return negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + else + return negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + }(); + + // Loop over positive tracks for (const auto& track1 : posThisColl) { if (!selectionTrackResonance(track1) || !selectionPIDKaonpTdependent(track1)) continue; + if constexpr (isMC) { + if (!track1.has_mcParticle()) + continue; + const auto& mcParticles = mcParticlesOpt.value().get(); + const auto track1McParticle = mcParticles.rawIteratorAt(track1.mcParticleId()); + if (track1McParticle.pdgCode() != PDG_t::kKPlus || !track1McParticle.isPhysicalPrimary()) + continue; + } + + // Loop over negative tracks for (const auto& track2 : negThisColl) { if (!selectionTrackResonance(track2) || !selectionPIDKaonpTdependent(track2)) continue; + if constexpr (isMC) { + if (!track2.has_mcParticle()) + continue; + const auto& mcParticles = mcParticlesOpt.value().get(); + const auto track2McParticle = mcParticles.rawIteratorAt(track2.mcParticleId()); + if (track2McParticle.pdgCode() != PDG_t::kKMinus || !track2McParticle.isPhysicalPrimary()) + continue; + } + + // Kinematic reconstruction (common for data and MC) ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); if (recPhi.Pt() < phiConfigs.minPhiPt) @@ -189,149 +252,492 @@ struct PhiMesonCandProducer { if (std::abs(recPhi.Rapidity()) > phiConfigs.cfgYAcceptance) continue; - histos.fill(HIST("h1PhiCandidateMass"), recPhi.M()); - - phimesonCandidatesData(collision.globalIndex(), recPhi.M(), recPhi.Pt(), recPhi.Rapidity(), recPhi.Phi()); + // PDG check and MC truth association for MCReco analysis + if constexpr (isMC) { + const auto& mcParticles = mcParticlesOpt.value().get(); + + const auto track1McParticle = mcParticles.rawIteratorAt(track1.mcParticleId()); + const auto track2McParticle = mcParticles.rawIteratorAt(track2.mcParticleId()); + + const auto track1mcPartMotherIndexes = track1McParticle.mothersIds(); + const auto track2mcPartMotherIndexes = track2McParticle.mothersIds(); + + auto genPhiMaybe = [&]() -> std::optional { + for (const auto& mother1Index : track1mcPartMotherIndexes) { + for (const auto& mother2Index : track2mcPartMotherIndexes) { + if (mother1Index != mother2Index) + continue; + const auto motherMcParticle = mcParticles.rawIteratorAt(mother1Index); + if (std::abs(motherMcParticle.pdgCode()) == o2::constants::physics::Pdg::kPhi) { + return motherMcParticle; + } + } + } + return std::nullopt; + }(); + + if (!genPhiMaybe) + continue; + const auto genPhi = *genPhiMaybe; + + phimesonCandidatesMcReco(collision.globalIndex(), recPhi.M(), genPhi.pt(), genPhi.y(), genPhi.phi()); + } else { + histos.fill(HIST("h3PhiCandidatesMass"), collision.centFT0M(), recPhi.Pt(), recPhi.M()); + phimesonCandidatesData(collision.globalIndex(), recPhi.M(), recPhi.Pt(), recPhi.Rapidity(), recPhi.Phi()); + } } } } + void processData(SelCollisions::iterator const& collision, FullTracks const&) + { + processPhiCandidates(collision); + } + PROCESS_SWITCH(PhiMesonCandProducer, processData, "Process function to select Phi meson candidates in Data or in McReco (w/o McTruth) analysis", true); - /* - void processMCRecoDataLike(SimCollisions::iterator const& collision, FullMCTracks const&) + void processMCReco(SimCollisions::iterator const& collision, FullMCTracks const&, aod::McParticles const& mcParticles) { - auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + processPhiCandidates(collision, mcParticles); + } - for (const auto& track1 : posThisColl) { - if (!selectionTrackResonance(track1) || !selectionPIDKaonpTdependent(track1)) + PROCESS_SWITCH(PhiMesonCandProducer, processMCReco, "Process function to select Phi meson candidates in MCReco w MC truth", false); + + /*void processFilteredData(FilteredSelCollisions::iterator const& collision, FullTracks const&) + { + processPhiCandidates(collision); + } + + PROCESS_SWITCH(PhiMesonCandProducer, processFilteredData, "Process function to select Phi meson candidates in filtered Data", true); + + void processFilteredMCReco(FilteredSimCollisions::iterator const& collision, FullMCTracks const&, aod::McParticles const& mcParticles) + { + processPhiCandidates(collision, mcParticles); + } + + PROCESS_SWITCH(PhiMesonCandProducer, processFilteredMCReco, "Process function to select Phi meson candidates in filtered MCReco w MC truth", false);*/ + + void processMCGen(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles) + { + for (const auto& mcParticle1 : mcParticles) { + if (!mcParticle1.isPhysicalPrimary() || std::abs(mcParticle1.eta()) > trackConfigs.etaMax) continue; - for (const auto& track2 : negThisColl) { - if (!selectionTrackResonance(track2) || !selectionPIDKaonpTdependent(track2)) + for (const auto& mcParticle2 : mcParticles) { + if (!mcParticle2.isPhysicalPrimary() || std::abs(mcParticle2.eta()) > trackConfigs.etaMax) continue; - ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); + if (!(mcParticle1.pdgCode() == PDG_t::kKPlus && mcParticle2.pdgCode() == PDG_t::kKMinus) && + !(mcParticle1.pdgCode() == PDG_t::kKMinus && mcParticle2.pdgCode() == PDG_t::kKPlus)) + continue; - if (recPhi.Pt() < phiConfigs.minPhiPt) + ROOT::Math::PxPyPzMVector genKPair = recMother(mcParticle1, mcParticle2, massKa, massKa); + + if (genKPair.Pt() < phiConfigs.minPhiPt) continue; - if (recPhi.M() > phiConfigs.maxMPhi) + if (genKPair.M() > phiConfigs.maxMPhi) continue; - if (std::abs(recPhi.Rapidity()) > phiConfigs.cfgYAcceptance) + if (std::abs(genKPair.Rapidity()) > phiConfigs.cfgYAcceptance) continue; - phimesonCandidatesData(collision.globalIndex(), recPhi.M(), recPhi.Pt(), recPhi.Rapidity(), recPhi.Phi()); + phimesonCandidatesMcGen(mcCollision.globalIndex(), genKPair.M(), genKPair.Pt(), genKPair.Rapidity(), genKPair.Phi()); } } } - PROCESS_SWITCH(PhiMesonCandProducer, processMCRecoDataLike, "Process function to select Phi meson candidates in MCReco w/o MC truth", false); - */ + PROCESS_SWITCH(PhiMesonCandProducer, processMCGen, "Process function to select Phi meson candidates in MCGen", false); +}; - void processMCReco(SimCollisions::iterator const& collision, FullMCTracks const&, aod::McParticles const& mcParticles) +struct K0sReducedCandProducer { + // Produce the table with the K0s candidates information + Produces k0sReducedCandidatesData; + Produces k0sReducedCandidatesMcReco; + + HistogramRegistry histos{"k0sReducedCandidates", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable on multiplicity bins + Configurable> binsMult{"binsMult", {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}, "Multiplicity bin limits"}; + + // Configurables for tracks selection + struct : ConfigurableGroup { + Configurable etaMax{"etaMax", 0.8f, "eta max"}; + Configurable nSigmaCutTPCSecPion{"nSigmaCutTPCSecPion", 4.0f, "Value of the TPC Nsigma cut for secondary Pions"}; + + Configurable minTPCnClsFound{"minTPCnClsFound", 70, "min number of found TPC clusters"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "min number of TPC crossed rows"}; + Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; + } trackConfigs; + + // Configurables for V0 selection + struct : ConfigurableGroup { + Configurable v0SettingCosPA{"v0SettingCosPA", 0.98f, "V0 CosPA"}; + Configurable v0SettingRadius{"v0SettingRadius", 0.5f, "v0radius"}; + Configurable v0SettingDCAV0Dau{"v0SettingDCAV0Dau", 1.0f, "DCA V0 Daughters"}; + Configurable v0SettingDCAPosToPV{"v0SettingDCAPosToPV", 0.1f, "DCA Pos To PV"}; + Configurable v0SettingDCANegToPV{"v0SettingDCANegToPV", 0.1f, "DCA Neg To PV"}; + Configurable v0SettingMinPt{"v0SettingMinPt", 0.1f, "V0 min pt"}; + + Configurable cfgFurtherV0Selection{"cfgFurtherV0Selection", false, "Further V0 selection"}; + Configurable ctauK0s{"ctauK0s", 20.0f, "C tau K0s(cm)"}; + Configurable paramArmenterosCut{"paramArmenterosCut", 0.2f, "parameter Armenteros Cut"}; + Configurable v0rejK0s{"v0rejK0s", 0.005f, "V0 rej K0s"}; + + Configurable> rangeMK0sSignal{"rangeMK0sSignal", {0.47f, 0.53f}, "K0S mass range for signal extraction"}; + + Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; + } v0Configs; + + // Configurable on K0S pT bins + Configurable> binspTK0S{"binspTK0S", {0.1, 0.5, 0.8, 1.2, 1.6, 2.0, 2.5, 3.0, 4.0, 6.0}, "pT bin limits for K0S"}; + + // Constants + static constexpr double massK0S = o2::constants::physics::MassK0Short; + static constexpr double massLambda = o2::constants::physics::MassLambda0; + + // Filter on default selected collisions + // Filter collisionFilter = aod::lf_selection_default_collision::defaultSel == true; + Filter collisionFilter = aod::lf_selection_event::defaultSel == true; + + // Defining filters on V0s (cannot filter on dynamic columns) + Filter v0PreFilter = (nabs(aod::v0data::dcapostopv) > v0Configs.v0SettingDCAPosToPV && nabs(aod::v0data::dcanegtopv) > v0Configs.v0SettingDCANegToPV && aod::v0data::dcaV0daughters < v0Configs.v0SettingDCAV0Dau); + + // Defining the type of the collisions for data and MC + using SelCollisions = soa::Join; + using SimCollisions = soa::Join; + + using FilteredSelCollisions = soa::Filtered; + using FilteredSimCollisions = soa::Filtered; + + // Defining the type of the V0s and corresponding daughter tracks for data and MC + using FullV0s = soa::Filtered; + using FullMCV0s = soa::Filtered>; + + using V0DauTracks = soa::Join; + using V0DauMCTracks = soa::Join; + + void init(InitContext&) { - auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + AxisSpec binnedmultAxis{(std::vector)binsMult, "centFT0M"}; + AxisSpec binnedpTK0SAxis{(std::vector)binspTK0S, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec massK0sAxis = {200, 0.4f, 0.6f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; - for (const auto& track1 : posThisColl) { - if (!selectionTrackResonance(track1) || !selectionPIDKaonpTdependent(track1)) + histos.add("h3K0sCandidatesMass", "K^{0}_{S} candidate invariant mass", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0sAxis}); + } + + // Single track selection for strangeness sector + template + bool selectionTrackStrangeness(const T& track) + { + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) + return false; + if (track.tpcNClsCrossedRows() < trackConfigs.minNCrossedRowsTPC) + return false; + if (track.tpcChi2NCl() > trackConfigs.maxChi2TPC) + return false; + + if (std::abs(track.eta()) > trackConfigs.etaMax) + return false; + return true; + } + + // V0 selection + template + bool selectionV0(const T1& v0, const T2& collision) + { + using V0DauTrackType = std::conditional_t; + + const auto& posDaughterTrack = v0.template posTrack_as(); + const auto& negDaughterTrack = v0.template negTrack_as(); + + if (!selectionTrackStrangeness(posDaughterTrack) || !selectionTrackStrangeness(negDaughterTrack)) + return false; + + if constexpr (!isMC) { + if (std::abs(posDaughterTrack.tpcNSigmaPi()) > trackConfigs.nSigmaCutTPCSecPion) + return false; + if (std::abs(negDaughterTrack.tpcNSigmaPi()) > trackConfigs.nSigmaCutTPCSecPion) + return false; + } + + if (v0.v0cosPA() < v0Configs.v0SettingCosPA) + return false; + if (v0.v0radius() < v0Configs.v0SettingRadius) + return false; + if (v0.pt() < v0Configs.v0SettingMinPt) + return false; + + if (v0Configs.cfgFurtherV0Selection) { + if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0S > v0Configs.ctauK0s) + return false; + if (v0.qtarm() < (v0Configs.paramArmenterosCut * std::abs(v0.alpha()))) + return false; + if (std::abs(v0.mLambda() - massLambda) < v0Configs.v0rejK0s) + return false; + } + + if (std::abs(v0.yK0Short()) > v0Configs.cfgYAcceptance) + return false; + + return true; + } + + // void processData(SelCollisions::iterator const& collision, FullV0s const& V0s, V0DauTracks const&) + void processData(FilteredSelCollisions::iterator const& collision, FullV0s const& V0s, V0DauTracks const&) + { + for (const auto& v0 : V0s) { + // Cut on V0 dynamic columns + if (!selectionV0(v0, collision)) continue; - if (!track1.has_mcParticle()) + + histos.fill(HIST("h3K0sCandidatesMass"), collision.centFT0M(), v0.pt(), v0.mK0Short()); + + k0sReducedCandidatesData(collision.globalIndex(), v0.mK0Short(), v0.pt(), v0.yK0Short(), v0.phi()); + } + } + + PROCESS_SWITCH(K0sReducedCandProducer, processData, "Process function to select reduced K0s candidates in Data or in McReco (w/o McTruth) analysis", true); + + // void processMCReco(SimCollisions::iterator const& collision, FullMCV0s const& V0s, V0DauMCTracks const&, aod::McParticles const& mcParticles) + void processMCReco(FilteredSimCollisions::iterator const& collision, FullMCV0s const& V0s, V0DauMCTracks const&, aod::McParticles const& mcParticles) + { + for (const auto& v0 : V0s) { + if (!selectionV0(v0, collision)) continue; - const auto track1McParticle = mcParticles.rawIteratorAt(track1.mcParticleId()); - if (track1McParticle.pdgCode() != PDG_t::kKPlus || !track1McParticle.isPhysicalPrimary()) + if (!v0.has_mcParticle()) continue; - for (const auto& track2 : negThisColl) { - if (!selectionTrackResonance(track2) || !selectionPIDKaonpTdependent(track2)) - continue; - if (!track2.has_mcParticle()) - continue; - const auto track2McParticle = mcParticles.rawIteratorAt(track2.mcParticleId()); - if (track2McParticle.pdgCode() != PDG_t::kKMinus || !track2McParticle.isPhysicalPrimary()) - continue; + const auto& v0McParticle = mcParticles.rawIteratorAt(v0.mcParticleId()); + if (std::abs(v0McParticle.pdgCode()) != PDG_t::kK0Short || !v0McParticle.isPhysicalPrimary()) + continue; - ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); + k0sReducedCandidatesMcReco(collision.globalIndex(), v0.mK0Short(), v0McParticle.pt(), v0McParticle.y(), v0McParticle.phi()); + } + } - if (recPhi.Pt() < phiConfigs.minPhiPt) - continue; - if (recPhi.M() > phiConfigs.maxMPhi) - continue; - if (std::abs(recPhi.Rapidity()) > phiConfigs.cfgYAcceptance) - continue; + PROCESS_SWITCH(K0sReducedCandProducer, processMCReco, "Process function to select reduced K0s candidates in MCReco w MC truth", false); +}; - const auto track1mcPartMotherIndexes = track1McParticle.mothersIds(); - const auto track2mcPartMotherIndexes = track2McParticle.mothersIds(); +struct PionTrackProducer { + // Produce the table with the pion tracks information + Produces pionTracksData; + Produces pionTracksMcReco; - auto genPhiMaybe = [&]() -> std::optional { - for (const auto& mother1Index : track1mcPartMotherIndexes) { - for (const auto& mother2Index : track2mcPartMotherIndexes) { - if (mother1Index != mother2Index) - continue; + HistogramRegistry histos{"pionTracks", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - const auto motherMcParticle = mcParticles.rawIteratorAt(mother1Index); - if (std::abs(motherMcParticle.pdgCode()) == o2::constants::physics::Pdg::kPhi) - return motherMcParticle; - } - } + // Configurable for analysis mode + Configurable analysisMode{"analysisMode", 1, "Analysis mode: 0 - old method with online normalization, 1 - new method with correlations"}; - return std::nullopt; - }(); + // Configurable on multiplicity bins + Configurable> binsMult{"binsMult", {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}, "Multiplicity bin limits"}; - if (!genPhiMaybe) - continue; - const auto genPhi = *genPhiMaybe; + // Configurables for pion track selection + struct : ConfigurableGroup { + Configurable cMinPionPtcut{"cMinPionPtcut", 0.2f, "Track minimum pt cut"}; + Configurable nSigmaCutTPCPrimPion{"nSigmaCutTPCPrimPion", 2.0f, "Value of the TPC Nsigma cut for primary Pions"}; + Configurable nSigmaCutCombinedPi{"nSigmaCutCombinedPi", 2.0f, "Value of the TPC and TOF Nsigma cut for Pions"}; + + Configurable cfgIsTOFChecked{"cfgIsTOFChecked", true, "Is TOF checked in PID for pions"}; + Configurable> cMaxDCArToPVPion{"cMaxDCArToPVPion", {0.004f, 0.013f, 1.0f}, "Track DCAr cut to PV for Pions"}; + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0f, "Track DCAz cut to PV Maximum"}; + Configurable cfgIsDCAzParameterized{"cfgIsDCAzParameterized", false, "IsDCAzParameterized"}; + Configurable> cMaxDCAzToPVPion{"cMaxDCAzToPVPion", {0.004f, 0.013f, 1.0f}, "Track DCAz cut to PV for Pions"}; + + Configurable minTPCnClsFound{"minTPCnClsFound", 70, "min number of found TPC clusters"}; + Configurable minITSnCls{"minITSnCls", 4, "min number of ITS clusters"}; + + Configurable forceTOF{"forceTOF", false, "force the TOF signal for the PID"}; + Configurable tofPIDThreshold{"tofPIDThreshold", 0.5, "minimum pT after which TOF PID is applicable"}; + Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton}, "Trk sel: Particles species for PID, proton, pion, kaon"}; + Configurable> pidTPCMax{"pidTPCMax", std::vector{2.0f, 2.0f, 2.0f}, "maximum nSigma TPC"}; + Configurable> pidTOFMax{"pidTOFMax", std::vector{2.0f, 2.0f, 2.0f}, "maximum nSigma TOF"}; + + Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; + } trackConfigs; + + // Configurable on pion pT bins + Configurable> binspTPi{"binspTPi", {0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.2, 1.5, 2.0, 3.0}, "pT bin limits for pions"}; + + static constexpr double massPi = o2::constants::physics::MassPiPlus; + + // Filter on default selected collisions + // Filter collisionFilter = aod::lf_selection_default_collision::defaultSel == true; + Filter collisionFilter = aod::lf_selection_event::defaultSel == true; - phimesonCandidatesMcReco(collision.globalIndex(), recPhi.M(), genPhi.pt(), genPhi.y(), genPhi.phi()); + // Defining the type of the collisions for data and MC + using SelCollisions = soa::Join; + using SimCollisions = soa::Join; + + using FilteredSelCollisions = soa::Filtered; + using FilteredSimCollisions = soa::Filtered; + + // Defining the type of the tracks for data and MC + using FullTracks = soa::Join; + using FullMCTracks = soa::Join; + + void init(InitContext&) + { + AxisSpec binnedmultAxis{(std::vector)binsMult, "centFT0M"}; + AxisSpec binnedpTPiAxis{(std::vector)binspTPi, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec nSigmaPiAxis = {100, -10.0f, 10.0f, "N#sigma #pi"}; + + histos.add("h3PionTPCnSigma", "Pion TPC nSigma distribution", kTH3F, {binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis}); + histos.add("h3PionTOFnSigma", "Pion TOF nSigma distribution", kTH3F, {binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis}); + + histos.add("h2RecMCDCAxyPrimPi", "Dcaxy distribution vs pt for Primary Pions", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + histos.add("h2RecMCDCAxySecWeakDecayPi", "Dcaz distribution vs pt for Secondary Pions from Weak Decay", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + histos.add("h2RecMCDCAxySecMaterialPi", "Dcaxy distribution vs pt for Secondary Pions from Material", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + } + + // PID selection for Pions + template + bool pidSelectionPion(const T& track) + { + for (size_t speciesIndex = 0; speciesIndex < trackConfigs.trkPIDspecies->size(); ++speciesIndex) { + auto const& pid = trackConfigs.trkPIDspecies->at(speciesIndex); + auto nSigmaTPC = aod::pidutils::tpcNSigma(pid, track); + + if (trackConfigs.forceTOF && !track.hasTOF()) { + return false; + } + + if (speciesIndex == 0) { // First species logic + if (std::abs(nSigmaTPC) >= trackConfigs.pidTPCMax->at(speciesIndex)) { + return false; // TPC check failed + } + if (trackConfigs.forceTOF || (track.pt() >= trackConfigs.tofPIDThreshold && track.hasTOF())) { + auto nSigmaTOF = aod::pidutils::tofNSigma(pid, track); + if (std::abs(nSigmaTOF) >= trackConfigs.pidTOFMax->at(speciesIndex)) { + return false; // TOF check failed + } + } + } else { // Other species logic + if (std::abs(nSigmaTPC) < trackConfigs.pidTPCMax->at(speciesIndex)) { // Check TPC nSigma first + if (track.hasTOF()) { + auto nSigmaTOF = aod::pidutils::tofNSigma(pid, track); + if (std::abs(nSigmaTOF) < trackConfigs.pidTOFMax->at(speciesIndex)) { + return false; // Reject if both TPC and TOF are within thresholds + } + } else { + return false; // Reject if only TPC is within threshold and TOF is unavailable + } + } } } + + return true; } - PROCESS_SWITCH(PhiMesonCandProducer, processMCReco, "Process function to select Phi meson candidates in MCReco w MC truth", false); + // Track selection for Pions + template + bool selectionPion(const T& track) + { + if (!track.isGlobalTrackWoDCA()) + return false; - void processMCGen(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles) + if (track.itsNCls() < trackConfigs.minITSnCls) + return false; + if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) + return false; + + if (track.pt() < trackConfigs.cMinPionPtcut) + return false; + + if (std::abs(track.dcaXY()) > trackConfigs.cMaxDCArToPVPion->at(0) + (trackConfigs.cMaxDCArToPVPion->at(1) / std::pow(track.pt(), trackConfigs.cMaxDCArToPVPion->at(2)))) + return false; + if (trackConfigs.cfgIsDCAzParameterized) { + if (std::abs(track.dcaZ()) > trackConfigs.cMaxDCAzToPVPion->at(0) + (trackConfigs.cMaxDCAzToPVPion->at(1) / std::pow(track.pt(), trackConfigs.cMaxDCAzToPVPion->at(2)))) + return false; + } else { + if (std::abs(track.dcaZ()) > trackConfigs.cMaxDCAzToPVcut) + return false; + } + + if (trackConfigs.cfgIsTOFChecked && track.pt() >= trackConfigs.tofPIDThreshold && !track.hasTOF()) + return false; + + if (analysisMode == 1 && !pidSelectionPion(track)) + return false; + + /* + if (analysisMode == 1) { + if (track.pt() < trackConfigs.tofPIDThreshold && std::abs(track.tpcNSigmaPi()) >= trackConfigs.nSigmaCutTPCPrimPion) + return false; + if (trackConfigs.cfgIsTOFChecked && track.pt() >= trackConfigs.tofPIDThreshold && (std::pow(track.tofNSigmaPi(), 2) + std::pow(track.tpcNSigmaPi(), 2)) >= std::pow(trackConfigs.nSigmaCutCombinedPi, 2)) + return false; + } + */ + + if (std::abs(track.rapidity(massPi)) > trackConfigs.cfgYAcceptance) + return false; + + return true; + } + + // void processData(SelCollisions::iterator const& collision, FullTracks const& fullTracks) + void processData(FilteredSelCollisions::iterator const& collision, FullTracks const& fullTracks) { - for (const auto& mcParticle1 : mcParticles) { - if (!mcParticle1.isPhysicalPrimary() || std::abs(mcParticle1.eta()) > trackConfigs.etaMax) + for (const auto& track : fullTracks) { + if (!selectionPion(track)) continue; - for (const auto& mcParticle2 : mcParticles) { - if (!mcParticle2.isPhysicalPrimary() || std::abs(mcParticle2.eta()) > trackConfigs.etaMax) - continue; + histos.fill(HIST("h3PionTPCnSigma"), collision.centFT0M(), track.pt(), track.tpcNSigmaPi()); + histos.fill(HIST("h3PionTOFnSigma"), collision.centFT0M(), track.pt(), track.tofNSigmaPi()); - if (!(mcParticle1.pdgCode() == PDG_t::kKPlus && mcParticle2.pdgCode() == PDG_t::kKMinus) && - !(mcParticle1.pdgCode() == PDG_t::kKMinus && mcParticle2.pdgCode() == PDG_t::kKPlus)) - continue; + pionTracksData(collision.globalIndex(), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt(), track.rapidity(massPi), track.phi()); + } + } - ROOT::Math::PxPyPzMVector genKPair = recMother(mcParticle1, mcParticle2, massKa, massKa); + PROCESS_SWITCH(PionTrackProducer, processData, "Process function to select pion tracks in Data or in McReco (w/o MC truth) analysis", true); - if (genKPair.Pt() < phiConfigs.minPhiPt) - continue; - if (genKPair.M() > phiConfigs.maxMPhi) - continue; - if (std::abs(genKPair.Rapidity()) > phiConfigs.cfgYAcceptance) - continue; + // void processMCReco(SimCollisions::iterator const& collision, FullMCTracks const& fullTracks, aod::McParticles const& mcParticles) + void processMCReco(FilteredSimCollisions::iterator const& collision, FullMCTracks const& fullTracks, aod::McParticles const& mcParticles) + { + for (const auto& track : fullTracks) { + if (!selectionPion(track)) + continue; + if (!track.has_mcParticle()) + continue; - phimesonCandidatesMcGen(mcCollision.globalIndex(), genKPair.M(), genKPair.Pt(), genKPair.Rapidity(), genKPair.Phi()); + const auto trackMcParticle = mcParticles.rawIteratorAt(track.mcParticleId()); + if (std::abs(trackMcParticle.pdgCode()) != PDG_t::kPiPlus) + continue; + + if (trackMcParticle.isPhysicalPrimary()) { + histos.fill(HIST("h2RecMCDCAxyPrimPi"), track.pt(), track.dcaXY()); + } else { + if (trackMcParticle.getProcess() == TMCProcess::kPDecay) { // Selection of secondary pions from weak decay + histos.fill(HIST("h2RecMCDCAxySecWeakDecayPi"), track.pt(), track.dcaXY()); + } else { // Selection of secondary pions from material interactions + histos.fill(HIST("h2RecMCDCAxySecMaterialPi"), track.pt(), track.dcaXY()); + } + continue; } + + pionTracksMcReco(collision.globalIndex(), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt(), track.rapidity(massPi), track.phi()); } } - PROCESS_SWITCH(PhiMesonCandProducer, processMCGen, "Process function to select Phi meson candidates in MCGen", false); + PROCESS_SWITCH(PionTrackProducer, processMCReco, "Process function to select pion tracks in MCReco w MC truth", false); }; -struct PhiMesonSelCollision { +struct EventSelectionProducer { // Produce the table with the event selection information + Produces phiStrangeEvtSelDataLike; + Produces phiStrangeEvtSelMcGen; + + // Produces phiStrangeDefEvtSelDataLike; + // Produces phiStrangeDefEvtSelMcGen; + + /*Produces defaultSelectionData; + Produces defaultSelectionMcGen; + Produces phimesonSelectionData; - // Produces phimesonSelectionMcReco; - Produces phimesonSelectionMcGen; + Produces phimesonSelectionMcGen;*/ HistogramRegistry histos{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - // Configurable for selection type - Configurable selectionType{"selectionType", 1, "Selection type: 0 - default selection only, 1 - default + phi meson selection"}; - // Configurable for event selection Configurable cutZVertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; @@ -393,13 +799,6 @@ struct PhiMesonSelCollision { histos.add("hMultiplicityPercentWPhi", "Multiplicity Percentile in Events with a Phi Candidate", kTH1F, {multAxis}); histos.add("h2VertexZvsMult", "Vertex Z vs Multiplicity Percentile", kTH2F, {vertexZAxis, binnedmultAxis}); histos.add("h2VertexZvsMultWPhi", "Vertex Z vs Multiplicity Percentile with a Phi Candidate", kTH2F, {vertexZAxis, binnedmultAxis}); - - // Phi's daughter tracks information - /*histos.add("hEta", "Eta of Kaon candidates", kTH1F, {{100, -1.0f, 1.0f}}); - histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); - histos.add("h2DauTracksPhiDCAxy", "DCAxy distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - histos.add("h2DauTracksPhiDCAz", "DCAz distribution vs pt", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}});*/ } // Default event selection @@ -500,31 +899,65 @@ struct PhiMesonSelCollision { return true; } - void processData(SelCollisions::iterator const& collision, aod::PhimesonCandidatesData const& phiCandidatesData) + // Default event selection + void processData(SelCollisions::iterator const& collision) + { + // phiStrangeDefEvtSelDataLike(defaultEventSelection(collision)); + phiStrangeEvtSelDataLike(defaultEventSelection(collision), false); + // defaultSelectionData(defaultEventSelection(collision), false); + } + + PROCESS_SWITCH(EventSelectionProducer, processData, "Process function to select default events in Data", true); + + void processMCReco(SimCollisions::iterator const& collision, MCCollisions const&) + { + // phiStrangeDefEvtSelDataLike(defaultEventSelection(collision)); + phiStrangeEvtSelDataLike(defaultEventSelection(collision), false); + // defaultSelectionData(defaultEventSelection(collision)); + } + + PROCESS_SWITCH(EventSelectionProducer, processMCReco, "Process function to select default events in MCReco", false); + + void processMCGen(MCCollisions::iterator const&, aod::McParticles const& mcParticles) + { + + // phiStrangeDefEvtSelMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB)); + phiStrangeEvtSelMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB), false); + // defaultSelectionMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB)); + } + + PROCESS_SWITCH(EventSelectionProducer, processMCGen, "Process function to select default events in MCGen", false); + + // Default event selection + phi meson requirement + void processDataWPhi(SelCollisions::iterator const& collision, aod::PhimesonCandidatesData const& phiCandidatesData) { - phimesonSelectionData(defaultEventSelection(collision) && selectionType == 1 ? eventHasPhi(collision, phiCandidatesData) : true); + phiStrangeEvtSelDataLike(defaultEventSelection(collision), eventHasPhi(collision, phiCandidatesData)); + // phimesonSelectionData(defaultEventSelection(collision) && eventHasPhi(collision, phiCandidatesData)); } - PROCESS_SWITCH(PhiMesonSelCollision, processData, "Process function to select events with Phi mesons in Data", true); + PROCESS_SWITCH(EventSelectionProducer, processDataWPhi, "Process function to select events with Phi mesons in Data", false); - void processMCReco(SimCollisions::iterator const& collision, MCCollisions const&, aod::PhimesonCandidatesData const& phiCandidatesData) + void processMCRecoWPhi(SimCollisions::iterator const& collision, MCCollisions const&, aod::PhimesonCandidatesData const& phiCandidatesData) { - // phimesonSelectionMcReco(defaultEventSelection(collision) && selectionType == 1 ? eventHasPhi(collision, phiCandidatesData) : true); - phimesonSelectionData(defaultEventSelection(collision) && selectionType == 1 ? eventHasPhi(collision, phiCandidatesData) : true); + phiStrangeEvtSelDataLike(defaultEventSelection(collision), eventHasPhi(collision, phiCandidatesData)); + // phimesonSelectionData(defaultEventSelection(collision) && eventHasPhi(collision, phiCandidatesData)); } - PROCESS_SWITCH(PhiMesonSelCollision, processMCReco, "Process function to select events with Phi mesons in MCReco", false); + PROCESS_SWITCH(EventSelectionProducer, processMCRecoWPhi, "Process function to select events with Phi mesons in MCReco", false); - void processMCGen(MCCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles, aod::PhimesonCandidatesMcGen const& phiCandidatesMcGen) + void processMCGenWPhi(MCCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles, aod::PhimesonCandidatesMcGen const& phiCandidatesMcGen) { - phimesonSelectionMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB) && selectionType == 1 ? eventHasPhi(mcCollision, phiCandidatesMcGen) : true); + phiStrangeEvtSelMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB), eventHasPhi(mcCollision, phiCandidatesMcGen)); + // phimesonSelectionMcGen(pwglf::isINELgt0mc(mcParticles, pdgDB) && eventHasPhi(mcCollision, phiCandidatesMcGen)); } - PROCESS_SWITCH(PhiMesonSelCollision, processMCGen, "Process function to select events with Phi mesons in MCGen", false); + PROCESS_SWITCH(EventSelectionProducer, processMCGenWPhi, "Process function to select events with Phi mesons in MCGen", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index f38b89125b5..01099001868 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -69,6 +69,7 @@ #include #include #include +#include #include #include @@ -151,7 +152,7 @@ struct PhiStrangenessCorrelation { HistogramRegistry histos{"phiStrangenessCorrelation", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for selection type - Configurable selectionType{"selectionType", 1, "Selection type: 0 - default selection only, 1 - default + phi meson selection"}; + Configurable eventSelectionType{"eventSelectionType", 0, "Event selection type: 0 - default selection only, 1 - default + phi meson selection"}; // Configurable for analysis mode Configurable analysisMode{"analysisMode", 1, "Analysis mode: 0 - old method with online normalization, 1 - new method with correlations"}; @@ -162,68 +163,20 @@ struct PhiStrangenessCorrelation { // Configurable on multiplicity bins Configurable> binsMult{"binsMult", {0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 70.0, 100.0}, "Multiplicity bin limits"}; - // Configurables for tracks selection + // Configurables on phi mass selection struct : ConfigurableGroup { - Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; - Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; - Configurable cMinKaonPtcut{"cMinKaonPtcut", 0.15f, "Track minimum pt cut"}; - Configurable etaMax{"etaMax", 0.8f, "eta max"}; - Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0f, "Track DCAz cut to PV Maximum"}; - Configurable> cMaxDCArToPVPhi{"cMaxDCArToPVPhi", {0.004f, 0.013f, 1.0f}, "Track DCAr cut to PV for Phi"}; - - Configurable cfgIsTOFChecked{"cfgIsTOFChecked", true, "Is TOF checked in PID for pions"}; - Configurable> cMaxDCArToPVPion{"cMaxDCArToPVPion", {0.004f, 0.013f, 1.0f}, "Track DCAr cut to PV for Pions"}; - Configurable cfgIsDCAzParameterized{"cfgIsDCAzParameterized", false, "IsDCAzParameterized"}; - Configurable> cMaxDCAzToPVPion{"cMaxDCAzToPVPion", {0.004f, 0.013f, 1.0f}, "Track DCAz cut to PV for Pions"}; - - Configurable nSigmaCutTPCKa{"nSigmaCutTPCKa", 2.0f, "Value of the TPC Nsigma cut for Kaons"}; - Configurable nSigmaCutCombinedKa{"nSigmaCutCombinedKa", 2.0f, "Value of the TPC and TOF Nsigma cut for Kaons"}; - - Configurable nSigmaCutTPCPrimPion{"nSigmaCutTPCPrimPion", 2.0f, "Value of the TPC Nsigma cut for primary Pions"}; - Configurable nSigmaCutTPCSecPion{"nSigmaCutTPCSecPion", 4.0f, "Value of the TPC Nsigma cut for secondary Pions"}; - Configurable nSigmaCutCombinedPi{"nSigmaCutCombinedPi", 2.0f, "Value of the TPC and TOF Nsigma cut for Pions"}; - Configurable cMinPionPtcut{"cMinPionPtcut", 0.2f, "Track minimum pt cut"}; - - Configurable minTPCnClsFound{"minTPCnClsFound", 70, "min number of found TPC clusters"}; - Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70, "min number of TPC crossed rows"}; - Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; - Configurable minITSnCls{"minITSnCls", 4, "min number of ITS clusters"}; - Configurable maxChi2ITS{"maxChi2ITS", 36.0f, "max chi2 per cluster ITS"}; - - Configurable forceTOF{"forceTOF", false, "force the TOF signal for the PID"}; - Configurable tofPIDThreshold{"tofPIDThreshold", 0.5, "minimum pT after which TOF PID is applicable"}; - Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton}, "Trk sel: Particles species for PID, proton, pion, kaon"}; - Configurable> pidTPCMax{"pidTPCMax", std::vector{2.0f, 2.0f, 2.0f}, "maximum nSigma TPC"}; - Configurable> pidTOFMax{"pidTOFMax", std::vector{2.0f, 2.0f, 2.0f}, "maximum nSigma TOF"}; - } trackConfigs; - - // Configurables on phi selection - struct : ConfigurableGroup { - Configurable minPhiPt{"minPhiPt", 0.4f, "Minimum pT for Phi candidates"}; Configurable> rangeMPhiSignal{"rangeMPhiSignal", {1.0095f, 1.029f}, "Phi mass range for signal extraction"}; Configurable> rangeMPhiSideband{"rangeMPhiSideband", {1.1f, 1.2f}, "Phi mass range for sideband extraction"}; } phiConfigs; - // Configurables on phi pT bins - Configurable> binspTPhi{"binspTPhi", {0.4, 0.8, 1.4, 2.0, 2.8, 4.0, 6.0, 10.0}, "pT bin limits for Phi"}; - - // Configurables for V0 selection + // Configurables for K0s selection struct : ConfigurableGroup { - Configurable v0SettingCosPA{"v0SettingCosPA", 0.98f, "V0 CosPA"}; - Configurable v0SettingRadius{"v0SettingRadius", 0.5f, "v0radius"}; - Configurable v0SettingDCAV0Dau{"v0SettingDCAV0Dau", 1.0f, "DCA V0 Daughters"}; - Configurable v0SettingDCAPosToPV{"v0SettingDCAPosToPV", 0.1f, "DCA Pos To PV"}; - Configurable v0SettingDCANegToPV{"v0SettingDCANegToPV", 0.1f, "DCA Neg To PV"}; - Configurable v0SettingMinPt{"v0SettingMinPt", 0.1f, "V0 min pt"}; - - Configurable cfgFurtherV0Selection{"cfgFurtherV0Selection", false, "Further V0 selection"}; - Configurable ctauK0s{"ctauK0s", 20.0f, "C tau K0s(cm)"}; - Configurable paramArmenterosCut{"paramArmenterosCut", 0.2f, "parameter Armenteros Cut"}; - Configurable v0rejK0s{"v0rejK0s", 0.005f, "V0 rej K0s"}; + Configurable selectK0sInSigRegion{"selectK0sInSigRegion", false, "Select K0s candidates in signal region"}; + Configurable> rangeMK0sSignal{"rangeMK0sSignal", {0.47f, 0.53f}, "K0S mass range for signal extraction"}; + } k0sConfigs; - Configurable lowMK0S{"lowMK0S", 0.48f, "Lower limit on K0Short mass"}; - Configurable upMK0S{"upMK0S", 0.52f, "Upper limit on K0Short mass"}; - } v0Configs; + // Configurables on phi pT bins + Configurable> binspTPhi{"binspTPhi", {0.4, 0.8, 1.4, 2.0, 2.8, 4.0, 6.0, 10.0}, "pT bin limits for Phi"}; // Configurable on K0S pT bins Configurable> binspTK0S{"binspTK0S", {0.1, 0.5, 0.8, 1.2, 1.6, 2.0, 2.5, 3.0, 4.0, 6.0}, "pT bin limits for K0S"}; @@ -250,57 +203,41 @@ struct PhiStrangenessCorrelation { Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository to use"}; Configurable ccdbEfficiencyPath{"ccdbEfficiencyPath", "Users/s/scannito/Efficiencies", "Correction path to file"}; - // Constants - double massPi = o2::constants::physics::MassPiPlus; - double massK0S = o2::constants::physics::MassK0Short; - double massLambda = o2::constants::physics::MassLambda0; + // Configurables for minimum pt selection in McGen + struct : ConfigurableGroup { + Configurable minPhiPt{"minPhiPt", 0.4f, "Minimum pT for Phi candidates"}; + Configurable v0SettingMinPt{"v0SettingMinPt", 0.1f, "V0 min pt"}; + Configurable cMinPionPtcut{"cMinPionPtcut", 0.2f, "Track minimum pt cut"}; + } minPtMcGenConfigs; // Filter on phi selected collisions - Filter collisionFilter = aod::lf_selection_phi_collision::phimesonSel == true; - - // Defining filters on V0s (cannot filter on dynamic columns) - Filter v0PreFilter = (nabs(aod::v0data::dcapostopv) > v0Configs.v0SettingDCAPosToPV && nabs(aod::v0data::dcanegtopv) > v0Configs.v0SettingDCANegToPV && aod::v0data::dcaV0daughters < v0Configs.v0SettingDCAV0Dau); + Filter collisionFilter = eventSelectionType == 0 && aod::lf_selection_event::defaultSel == true || + eventSelectionType == 1 && aod::lf_selection_event::defaultSel == true && aod::lf_selection_event::phimesonSel == true; // Defining the type of the collisions for data and MC - using SelCollisions = soa::Filtered>; - using SimCollisions = soa::Join; - // using SimCollisions = soa::Filtered>; - using MCCollisions = soa::Filtered>; - - // Defining the type of the V0s and corresponding daughter tracks for data and MC - using FullV0s = soa::Filtered; - using FullMCV0s = soa::Join; - - using V0DauTracks = soa::Join; - using V0DauMCTracks = soa::Join; - - // Defining the type of the tracks for data and MC - using FullTracks = soa::Join; - using FullMCTracks = soa::Join; - - // using FilteredTracks = soa::Filtered; - // using FilteredMCTracks = soa::Filtered; + using SelCollisions = soa::Filtered>; + using SimCollisions = soa::Filtered>; + using MCCollisions = soa::Filtered>; // Slice cache and Preslices for table slicing SliceCache cache; struct : PresliceGroup { - Preslice v0PerCollision = aod::v0::collisionId; - Preslice trackPerCollision = aod::track::collisionId; - Preslice mcPartPerMcCollision = aod::mcparticle::mcCollisionId; Preslice phiCandDataPerCollision = aod::lf_selection_phi_candidate::collisionId; - PresliceUnsorted phiCandPerCollision = aod::lf_selection_phi_candidate::collisionId; + PresliceUnsorted phiCandMcRecoPerCollision = aod::lf_selection_phi_candidate::collisionId; + + Preslice k0sDataPerCollision = aod::v0::collisionId; + Preslice k0sMcRecoPerCollision = aod::v0::collisionId; + + Preslice pionTrackDataPerCollision = aod::track::collisionId; + Preslice pionTrackMcRecoPerCollision = aod::track::collisionId; + + Preslice mcPartPerMcCollision = aod::mcparticle::mcCollisionId; } preslices; // Necessary service to retrieve efficiency maps from CCDB Service ccdb; - // Efficiency maps - /*std::shared_ptr effMapPhi = nullptr; - std::shared_ptr effMapK0S = nullptr; - std::shared_ptr effMapPionTPC = nullptr; - std::shared_ptr effMapPionTPCTOF = nullptr;*/ - std::array, ParticleOfInterestSize> effMaps{}; // Binning policy and axes for mixed event @@ -335,10 +272,6 @@ struct PhiStrangenessCorrelation { histos.add(fmt::format("phiPi/h5PhiPiDataME{}", label).c_str(), "Deltay vs deltaphi for Phi and Pion in Data ME", kTHnSparseF, {binnedmultAxis, binnedpTPhiAxis, binnedpTPiAxis, deltayAxis, deltaphiAxis}); } - // histos.add("phiK0S/h5PhiK0SDataNewProc", "2D Invariant mass of Phi and K0Short in Data", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTK0SAxis, massK0SAxis, massPhiAxis}); - // histos.add("phiPi/h5PhiPiTPCDataNewProc", "Phi Invariant mass vs Pion nSigma TPC in Data", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); - // histos.add("phiPi/h5PhiPiTOFDataNewProc", "Phi Invariant mass vs Pion nSigma TOF in Data", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); - histos.add("event/hRecoMCMultiplicityPercent", "RecoMC Multiplicity Percentile", kTH1F, {binnedmultAxis}); histos.add("event/h2RecoMCVertexZvsMult", "RecoMC Vertex Z vs Multiplicity Percentile", kTH2F, {vertexZAxis, binnedmultAxis}); histos.add("event/hSplitVertexZ", "Split in z-vtx", kTH1F, {{100, -5.0f, 5.0f}}); @@ -400,154 +333,7 @@ struct PhiStrangenessCorrelation { return RecoDecay::constrainAngle(phiTrigger - phiAssociated, -o2::constants::math::PIHalf); } - // Single track selection for strangeness sector - template - bool selectionTrackStrangeness(const T& track) - { - if (!track.hasTPC()) - return false; - if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) - return false; - if (track.tpcNClsCrossedRows() < trackConfigs.minNCrossedRowsTPC) - return false; - if (track.tpcChi2NCl() > trackConfigs.maxChi2TPC) - return false; - - if (std::abs(track.eta()) > trackConfigs.etaMax) - return false; - return true; - } - - // V0 selection - template - bool selectionV0(const T1& v0, const T2& collision) - { - using V0DauTrackType = std::conditional_t; - - const auto& posDaughterTrack = v0.template posTrack_as(); - const auto& negDaughterTrack = v0.template negTrack_as(); - - // const auto& posDaughterTrack = v0.template posTrack_as(); - // const auto& negDaughterTrack = v0.template negTrack_as(); - - if (!selectionTrackStrangeness(posDaughterTrack) || !selectionTrackStrangeness(negDaughterTrack)) - return false; - - if constexpr (!isMC) { - if (std::abs(posDaughterTrack.tpcNSigmaPi()) > trackConfigs.nSigmaCutTPCSecPion) - return false; - if (std::abs(negDaughterTrack.tpcNSigmaPi()) > trackConfigs.nSigmaCutTPCSecPion) - return false; - } - - if (v0.v0cosPA() < v0Configs.v0SettingCosPA) - return false; - if (v0.v0radius() < v0Configs.v0SettingRadius) - return false; - if (v0.pt() < v0Configs.v0SettingMinPt) - return false; - - if (v0Configs.cfgFurtherV0Selection) { - if (v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0S > v0Configs.ctauK0s) - return false; - if (v0.qtarm() < (v0Configs.paramArmenterosCut * std::abs(v0.alpha()))) - return false; - if (std::abs(v0.mLambda() - massLambda) < v0Configs.v0rejK0s) - return false; - } - - if (std::abs(v0.yK0Short()) > yConfigs.cfgYAcceptance) - return false; - - return true; - } - - // PID selection for Pions - template - bool pidSelectionPion(const T& track) - { - for (size_t speciesIndex = 0; speciesIndex < trackConfigs.trkPIDspecies->size(); ++speciesIndex) { - auto const& pid = trackConfigs.trkPIDspecies->at(speciesIndex); - auto nSigmaTPC = aod::pidutils::tpcNSigma(pid, track); - - if (trackConfigs.forceTOF && !track.hasTOF()) { - return false; - } - - if (speciesIndex == 0) { // First species logic - if (std::abs(nSigmaTPC) >= trackConfigs.pidTPCMax->at(speciesIndex)) { - return false; // TPC check failed - } - if (trackConfigs.forceTOF || (track.pt() >= trackConfigs.tofPIDThreshold && track.hasTOF())) { - auto nSigmaTOF = aod::pidutils::tofNSigma(pid, track); - if (std::abs(nSigmaTOF) >= trackConfigs.pidTOFMax->at(speciesIndex)) { - return false; // TOF check failed - } - } - } else { // Other species logic - if (std::abs(nSigmaTPC) < trackConfigs.pidTPCMax->at(speciesIndex)) { // Check TPC nSigma first - if (track.hasTOF()) { - auto nSigmaTOF = aod::pidutils::tofNSigma(pid, track); - if (std::abs(nSigmaTOF) < trackConfigs.pidTOFMax->at(speciesIndex)) { - return false; // Reject if both TPC and TOF are within thresholds - } - } else { - return false; // Reject if only TPC is within threshold and TOF is unavailable - } - } - } - } - - return true; - } - - // Track selection for Pions - template - bool selectionPion(const T& track) - { - if (!track.isGlobalTrackWoDCA()) - return false; - - if (track.itsNCls() < trackConfigs.minITSnCls) - return false; - if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) - return false; - - if (track.pt() < trackConfigs.cMinPionPtcut) - return false; - - if (std::abs(track.dcaXY()) > trackConfigs.cMaxDCArToPVPion->at(0) + (trackConfigs.cMaxDCArToPVPion->at(1) / std::pow(track.pt(), trackConfigs.cMaxDCArToPVPion->at(2)))) - return false; - if (trackConfigs.cfgIsDCAzParameterized) { - if (std::abs(track.dcaZ()) > trackConfigs.cMaxDCAzToPVPion->at(0) + (trackConfigs.cMaxDCAzToPVPion->at(1) / std::pow(track.pt(), trackConfigs.cMaxDCAzToPVPion->at(2)))) - return false; - } else { - if (std::abs(track.dcaZ()) > trackConfigs.cMaxDCAzToPVcut) - return false; - } - - if (trackConfigs.cfgIsTOFChecked && track.pt() >= trackConfigs.tofPIDThreshold && !track.hasTOF()) - return false; - - if (analysisMode == 1 && !pidSelectionPion(track)) - return false; - - /* - if (analysisMode == 1) { - if (track.pt() < trackConfigs.tofPIDThreshold && std::abs(track.tpcNSigmaPi()) >= trackConfigs.nSigmaCutTPCPrimPion) - return false; - if (trackConfigs.cfgIsTOFChecked && track.pt() >= trackConfigs.tofPIDThreshold && (std::pow(track.tofNSigmaPi(), 2) + std::pow(track.tpcNSigmaPi(), 2)) >= std::pow(trackConfigs.nSigmaCutCombinedPi, 2)) - return false; - } - */ - - if (std::abs(track.rapidity(massPi)) > yConfigs.cfgYAcceptance) - return false; - - return true; - } - - void processPhiK0SPionData(SelCollisions::iterator const& collision, aod::PhimesonCandidatesData const& phiCandidates, FullTracks const& fullTracks, FullV0s const& V0s, V0DauTracks const&) + void processPhiK0SPionData(SelCollisions::iterator const& collision, aod::PhimesonCandidatesData const& phiCandidates, aod::K0sReducedCandidatesData const& k0sReduced, aod::PionTracksData const& pionTracks) { float multiplicity = collision.centFT0M(); @@ -556,48 +342,35 @@ struct PhiStrangenessCorrelation { for (const auto& phiCand : phiCandidates) { float weightPhi = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y())); - // float weightPhi = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y())); - histos.fill(HIST("phi/h3PhiData"), multiplicity, phiCand.pt(), phiCand.m(), weightPhi); static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { constexpr unsigned int i = i_idx.value; - const auto& [minMass, maxMass] = phiMassRegions[i]; - if (!phiCand.inMassRegion(minMass, maxMass)) + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) return; - // V0 already reconstructed by the builder - for (const auto& v0 : V0s) { - // Cut on V0 dynamic columns - if (!selectionV0(v0, collision)) - continue; + // Loop over all reduced K0S candidates + for (const auto& k0s : k0sReduced) { + if (k0sConfigs.selectK0sInSigRegion) { + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; + if (!k0s.inMassRegion(minMassK0s, maxMassK0s)) + continue; + } float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMaps[K0S], multiplicity, v0.pt(), v0.yK0Short())); - - /*float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMapK0S, multiplicity, v0.pt(), v0.yK0Short()));*/ + BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); - histos.fill(HIST("phiK0S/h5PhiK0SData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), v0.pt(), phiCand.y() - v0.yK0Short(), getDeltaPhi(phiCand.phi(), v0.phi()), weightPhiK0S); + histos.fill(HIST("phiK0S/h5PhiK0SData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), weightPhiK0S); } // Loop over all primary pion candidates - for (const auto& track : fullTracks) { - if (!selectionPion(track)) - continue; - - // auto Pion = track.pt() < trackConfigs.tofPIDThreshold ? PionTPC : PionTPCTOF; - + for (const auto& pionTrack : pionTracks) { float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMaps[Pion], multiplicity, track.pt(), track.rapidity(massPi))); - - /*auto effMapPion = track.pt() < trackConfigs.tofPIDThreshold ? effMapPionTPC : effMapPionTPCTOF; - - float weightPhiPion = computeWeight(BoundEfficiencyMap(effMapPhi, multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMapPion, multiplicity, track.pt(), track.rapidity(massPi)));*/ + BoundEfficiencyMap(effMaps[Pion], multiplicity, pionTrack.pt(), pionTrack.y())); - histos.fill(HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), track.pt(), phiCand.y() - track.rapidity(massPi), getDeltaPhi(phiCand.phi(), track.phi()), weightPhiPion); + histos.fill(HIST("phiPi/h5PhiPiData") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), pionTrack.pt(), phiCand.y() - pionTrack.y(), getDeltaPhi(phiCand.phi(), pionTrack.phi()), weightPhiPion); } }); } @@ -605,32 +378,35 @@ struct PhiStrangenessCorrelation { PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SPionData, "Process function for Phi-K0S and Phi-Pion Deltay and Deltaphi 2D Correlations in Data", true); - void processPhiK0SDataME(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, FullV0s const& V0s, V0DauTracks const&) + void processPhiK0SDataME(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, aod::K0sReducedCandidatesData const& k0sReduced) { const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; - auto tuplePhiV0 = std::make_tuple(phiCandidates, V0s); - Pair pairPhiK0S{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiV0, &cache}; + auto tuplePhiK0S = std::make_tuple(phiCandidates, k0sReduced); + Pair pairPhiK0S{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiK0S, &cache}; - for (const auto& [c1, phiCands, c2, v0s] : pairPhiK0S) { + for (const auto& [c1, phiCands, c2, k0sRed] : pairPhiK0S) { float multiplicity = c1.centFT0M(); - for (const auto& [phiCand, v0] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, v0s))) { + for (const auto& [phiCand, k0s] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, k0sRed))) { static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { constexpr unsigned int i = i_idx.value; - const auto& [minMass, maxMass] = phiMassRegions[i]; - if (!phiCand.inMassRegion(minMass, maxMass)) + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) return; - if (!selectionV0(v0, c2)) - return; + if (k0sConfigs.selectK0sInSigRegion) { + const auto& [minMassK0s, maxMassK0s] = k0sConfigs.rangeMK0sSignal.value; + if (!k0s.inMassRegion(minMassK0s, maxMassK0s)) + return; + } float weightPhiK0S = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMaps[K0S], multiplicity, v0.pt(), v0.yK0Short())); + BoundEfficiencyMap(effMaps[K0S], multiplicity, k0s.pt(), k0s.y())); - histos.fill(HIST("phiK0S/h5PhiK0SDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), v0.pt(), phiCand.y() - v0.yK0Short(), getDeltaPhi(phiCand.phi(), v0.phi()), weightPhiK0S); + histos.fill(HIST("phiK0S/h5PhiK0SDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), k0s.pt(), phiCand.y() - k0s.y(), getDeltaPhi(phiCand.phi(), k0s.phi()), weightPhiK0S); }); } } @@ -638,32 +414,29 @@ struct PhiStrangenessCorrelation { PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiK0SDataME, "Process function for Phi-K0S and Deltay and Deltaphi 2D Correlations in Data ME", false); - void processPhiPionDataME(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, FullTracks const& fullTracks) + void processPhiPionDataME(SelCollisions const& collisions, aod::PhimesonCandidatesData const& phiCandidates, aod::PionTracksData const& pionTracks) { const std::array, 2> phiMassRegions = {phiConfigs.rangeMPhiSignal, phiConfigs.rangeMPhiSideband}; - auto tuplePhiPion = std::make_tuple(phiCandidates, fullTracks); - Pair pairPhiPion{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiPion, &cache}; + auto tuplePhiPion = std::make_tuple(phiCandidates, pionTracks); + Pair pairPhiPion{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tuplePhiPion, &cache}; - for (const auto& [c1, phiCands, c2, tracks] : pairPhiPion) { + for (const auto& [c1, phiCands, c2, piTracks] : pairPhiPion) { float multiplicity = c1.centFT0M(); - for (const auto& [phiCand, track] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, tracks))) { + for (const auto& [phiCand, piTrack] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(phiCands, piTracks))) { static_for<0, phiMassRegionLabels.size() - 1>([&](auto i_idx) { constexpr unsigned int i = i_idx.value; - const auto& [minMass, maxMass] = phiMassRegions[i]; - if (!phiCand.inMassRegion(minMass, maxMass)) - return; - - if (!selectionPion(track)) + const auto& [minMassPhi, maxMassPhi] = phiMassRegions[i]; + if (!phiCand.inMassRegion(minMassPhi, maxMassPhi)) return; float weightPhiPion = computeWeight(BoundEfficiencyMap(effMaps[Phi], multiplicity, phiCand.pt(), phiCand.y()), - BoundEfficiencyMap(effMaps[Pion], multiplicity, track.pt(), track.rapidity(massPi))); + BoundEfficiencyMap(effMaps[Pion], multiplicity, piTrack.pt(), piTrack.y())); - histos.fill(HIST("phiPi/h5PhiPiDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), track.pt(), phiCand.y() - track.rapidity(massPi), getDeltaPhi(phiCand.phi(), track.phi()), weightPhiPion); + histos.fill(HIST("phiPi/h5PhiPiDataME") + HIST(phiMassRegionLabels[i]), multiplicity, phiCand.pt(), piTrack.pt(), phiCand.y() - piTrack.y(), getDeltaPhi(phiCand.phi(), piTrack.phi()), weightPhiPion); }); } } @@ -671,9 +444,11 @@ struct PhiStrangenessCorrelation { PROCESS_SWITCH(PhiStrangenessCorrelation, processPhiPionDataME, "Process function for Phi-Pion Deltay and Deltaphi 2D Correlations in Data ME", false); - void processParticleEfficiency(MCCollisions const& mcCollisions, SimCollisions const& collisions, FullMCTracks const& fullMCTracks, FullMCV0s const& V0s, V0DauMCTracks const&, aod::McParticles const& mcParticles, aod::PhimesonCandidatesMcReco const& phiCandidatesMcReco) + void processParticleEfficiency(MCCollisions const& mcCollisions, SimCollisions const& collisions, aod::PhimesonCandidatesMcReco const& phiCandidates, aod::K0sReducedCandidatesMcReco const& k0sReduced, aod::PionTracksMcReco const& pionTracks, aod::McParticles const& mcParticles) { - std::vector> collsGrouped(mcCollisions.size()); + // std::vector> collsGrouped(mcCollisions.size()); + std::unordered_map> collsGrouped; + collsGrouped.reserve(mcCollisions.size()); for (const auto& collision : collisions) { if (!collision.has_mcCollision()) @@ -682,70 +457,46 @@ struct PhiStrangenessCorrelation { collsGrouped[mcCollision.globalIndex()].push_back(collision.globalIndex()); } + std::vector zVtxs; + zVtxs.reserve(3); // Reasonable number of associated collisions to expect at most + for (const auto& mcCollision : mcCollisions) { uint16_t numberAssocColls{0}; - std::vector zVtxs; + zVtxs.clear(); - const auto& collIndexesThisMcColl = collsGrouped[mcCollision.globalIndex()]; + // const auto& collIndexesThisMcColl = collsGrouped[mcCollision.globalIndex()]; + auto it = collsGrouped.find(mcCollision.globalIndex()); + if (it != collsGrouped.end()) { + const auto& collIndexesThisMcColl = it->second; - for (const auto& collIndex : collIndexesThisMcColl) { - const auto& collision = collisions.rawIteratorAt(collIndex); + for (const auto& collIndex : collIndexesThisMcColl) { + const auto& collision = collisions.rawIteratorAt(collIndex); - histos.fill(HIST("event/hRecoMCMultiplicityPercent"), mcCollision.centFT0M()); - histos.fill(HIST("event/h2RecoMCVertexZvsMult"), collision.posZ(), mcCollision.centFT0M()); + histos.fill(HIST("event/hRecoMCMultiplicityPercent"), mcCollision.centFT0M()); + histos.fill(HIST("event/h2RecoMCVertexZvsMult"), collision.posZ(), mcCollision.centFT0M()); - zVtxs.push_back(collision.posZ()); + zVtxs.push_back(collision.posZ()); - if (selectionType == 0) { - const auto phiCandidatesThisColl = phiCandidatesMcReco.sliceBy(preslices.phiCandPerCollision, collision.globalIndex()); - for (const auto& phiCand : phiCandidatesThisColl) { - histos.fill(HIST("phi/h4PhiMCReco"), collision.posZ(), mcCollision.centFT0M(), phiCand.pt(), phiCand.y()); + if (eventSelectionType == 0) { + const auto phiCandidatesThisColl = phiCandidates.sliceBy(preslices.phiCandMcRecoPerCollision, collision.globalIndex()); + for (const auto& phiCand : phiCandidatesThisColl) { + histos.fill(HIST("phi/h4PhiMCReco"), collision.posZ(), mcCollision.centFT0M(), phiCand.pt(), phiCand.y()); + } } - } - - const auto v0sThisColl = V0s.sliceBy(preslices.v0PerCollision, collision.globalIndex()); - const auto fullMCTracksThisColl = fullMCTracks.sliceBy(preslices.trackPerCollision, collision.globalIndex()); - - for (const auto& v0 : v0sThisColl) { - if (!selectionV0(v0, collision)) - continue; - if (!v0.has_mcParticle()) - continue; - - const auto& v0McParticle = mcParticles.rawIteratorAt(v0.mcParticleId()); - if (std::abs(v0McParticle.pdgCode()) != PDG_t::kK0Short || !v0McParticle.isPhysicalPrimary()) - continue; - - histos.fill(HIST("k0s/h4K0SMCReco"), collision.posZ(), mcCollision.centFT0M(), v0McParticle.pt(), v0McParticle.y()); - } + const auto k0sThisColl = k0sReduced.sliceBy(preslices.k0sMcRecoPerCollision, collision.globalIndex()); + const auto pionTracksThisColl = pionTracks.sliceBy(preslices.pionTrackMcRecoPerCollision, collision.globalIndex()); - for (const auto& track : fullMCTracksThisColl) { - if (!selectionPion(track)) - continue; - - if (!track.has_mcParticle()) - continue; - - const auto& trackMcParticle = mcParticles.rawIteratorAt(track.mcParticleId()); - if (std::abs(trackMcParticle.pdgCode()) != PDG_t::kPiPlus) - continue; + for (const auto& k0s : k0sThisColl) { + histos.fill(HIST("k0s/h4K0SMCReco"), collision.posZ(), mcCollision.centFT0M(), k0s.pt(), k0s.y()); + } - if (trackMcParticle.isPhysicalPrimary()) { - histos.fill(HIST("pi/h2RecMCDCAxyPrimPi"), track.pt(), track.dcaXY()); - } else { - if (trackMcParticle.getProcess() == TMCProcess::kPDecay) { // Selection of secondary pions from weak decay - histos.fill(HIST("pi/h2RecMCDCAxySecWeakDecayPi"), track.pt(), track.dcaXY()); - } else { // Selection of secondary pions from material interactions - histos.fill(HIST("pi/h2RecMCDCAxySecMaterialPi"), track.pt(), track.dcaXY()); - } - continue; + for (const auto& pionTrack : pionTracksThisColl) { + histos.fill(HIST("pi/h4PiMCReco"), collision.posZ(), mcCollision.centFT0M(), pionTrack.pt(), pionTrack.y()); } - histos.fill(HIST("pi/h4PiMCReco"), collision.posZ(), mcCollision.centFT0M(), trackMcParticle.pt(), trackMcParticle.y()); + numberAssocColls++; } - - numberAssocColls++; } histos.fill(HIST("event/hGenMCMultiplicityPercent"), mcCollision.centFT0M()); @@ -784,15 +535,15 @@ struct PhiStrangenessCorrelation { switch (std::abs(mcParticle.pdgCode())) { case o2::constants::physics::Pdg::kPhi: - if (selectionType == 0 && mcParticle.pt() >= phiConfigs.minPhiPt) + if (eventSelectionType == 0 && mcParticle.pt() >= minPtMcGenConfigs.minPhiPt) fillGenHistos(HIST("phi/h3PhiMCGen"), HIST("phi/h4PhiMCGenAssocReco"), mcParticle); break; case PDG_t::kK0Short: - if (mcParticle.isPhysicalPrimary() && mcParticle.pt() >= v0Configs.v0SettingMinPt) + if (mcParticle.isPhysicalPrimary() && mcParticle.pt() >= minPtMcGenConfigs.v0SettingMinPt) fillGenHistos(HIST("k0s/h3K0SMCGen"), HIST("k0s/h4K0SMCGenAssocReco"), mcParticle); break; case PDG_t::kPiPlus: - if (mcParticle.isPhysicalPrimary() && mcParticle.pt() >= trackConfigs.cMinPionPtcut) + if (mcParticle.isPhysicalPrimary() && mcParticle.pt() >= minPtMcGenConfigs.cMinPionPtcut) fillGenHistos(HIST("pi/h3PiMCGen"), HIST("pi/h4PiMCGenAssocReco"), mcParticle); break; default: From 9ef2e9bae5a3b355149f40fcb265c64f0568dc32 Mon Sep 17 00:00:00 2001 From: scannito Date: Sat, 21 Feb 2026 17:13:52 +0100 Subject: [PATCH 2/2] Fix for warning --- PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx index 01099001868..b427eafa899 100644 --- a/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/phiStrangeCorrelation.cxx @@ -211,8 +211,8 @@ struct PhiStrangenessCorrelation { } minPtMcGenConfigs; // Filter on phi selected collisions - Filter collisionFilter = eventSelectionType == 0 && aod::lf_selection_event::defaultSel == true || - eventSelectionType == 1 && aod::lf_selection_event::defaultSel == true && aod::lf_selection_event::phimesonSel == true; + Filter collisionFilter = (eventSelectionType == 0 && aod::lf_selection_event::defaultSel == true) || + (eventSelectionType == 1 && aod::lf_selection_event::defaultSel == true && aod::lf_selection_event::phimesonSel == true); // Defining the type of the collisions for data and MC using SelCollisions = soa::Filtered>;